admin管理员组文章数量:1321253
I have a problem with Android Compose. It does not track the state of some variables as I would expect it too. Basically it does not track at all or sometimes not in real time what changed. I do the following:
In my NavHost or better said before I define the uiState by remember:
val uiState by viewModel.uiState.collectAsState()
NavHost(
navController = navController,
startDestination = AppMenu.Dex.name,
modifier = modifier,
){
composable(route = AppMenu.Dex.name) {
DexScreen(
viewModel = viewModel,
)
}
composable(route = AppMenu.Statistics.name) {
StatisticsScreen(
dexUiState = uiState,
viewModel = viewModel
)
}
After that I have in my StatisticsScrren:
fun StatisticsScreen(
dexUiState: DexUiState,
viewModel: CollectionViewModel,
modifier: Modifier = Modifier,
) {
val uiState by viewModel.uiState.collectAsState()
LazyColumn(modifier = modifier) {
items(uiState.packs) { pack ->
PackStatistics(pack)
}
}
}
@Composable
fun PackStatistics(
pack: PackEntry,
modifier: Modifier = Modifier,
) {
val diamond:String = pack.collectedDiamond.toString() + "/" + pack.totalDiamond.toString()
val star:String = pack.collectedStar.toString() + "/" + pack.totalStar.toString()
Column {
Text(stringResource(pack.packId))
Row {
Spacer(modifier = modifier.weight(1f))
Icon(
imageVector = SuitDiamond,
contentDescription = null,
modifier.padding(end = 3.dp, top = 4.dp)
)
Text(
text = diamond
)
Icon(
imageVector = Icons.Default.Star,
contentDescription = null,
modifier.padding(start = 10.dp, end = 3.dp)
)
Text(
text = star
)
}
}
}
So I take the values of uiState (I tried it either by defining the uiState in the StatisticsScreen as well as in the NavHost before, but it doesnt change anything.
I update the state in the ViewModel defined as follows:
private const val TAG: String = "DexScreenViewModel"
class CollectionViewModel(
private val saveStateRepo: SaveStateRepo,
private val settingsRepo: SettingsRepository
): ViewModel() {
private val _uiState = MutableStateFlow((DexUiState()))
val uiState: StateFlow<DexUiState> =
combine(_uiState, settingsRepo.dexWidthSetting) {uiState, dexColumns ->
uiState.copy(dexColumns = dexColumns)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(1),
initialValue = DexUiState()
)
private fun load() {
runBlocking {
Log.d(TAG, "Start Settings load")
val settingDexWidth = settingsRepo.dexWidthSetting.first()
_uiState.update { currentState ->
currentState.copy( dexColumns = settingDexWidth)
}
_uiState.value = _uiState.value.copy(dexColumns = settingDexWidth)
Log.d(TAG, "Finished Settings load")
}
Log.d(TAG, "Started loading")
viewModelScope.launch {
Log.d(TAG, "Launched loading")
saveStateRepo.getAllSaved()
.collect{ savedDexEntry ->
val dbSavedMap = savedDexEntry.associateBy {it.cardId}
val updatedDex = Dex().loadDex()
.map { dexEntry: DexEntry ->
dbSavedMap[dexEntry.cardId]?.let { dbCard ->
dexEntry.copy(numberPossession = dbCard.inPossession)
} ?: dexEntry
}
_uiState.value = DexUiState(
packs = Packs().loadPacks().toMutableList(),
dex = updatedDex.toMutableList(),
dexColumns = 3,
)
val newDexList : MutableList<DexEntry> = mutableListOf()
for (dexEntry in _uiState.value.dex) {
//Log.d(TAG, "Starting searching Dex")
newDexList.add(
checkActive(dexEntry = dexEntry)
)
}
val newPackList: MutableList<PackEntry> = mutableListOf()
for (packEntry in _uiState.value.packs) {
newPackList.add(
calcRarity(packEntry = packEntry)
)
}
_uiState.update { currentState ->
currentState.copy(packs = newPackList, dex = newDexList)
}
}
}
val newDexList : MutableList<DexEntry> = mutableListOf()
for (dexEntry in _uiState.value.dex) {
newDexList.add(
checkActive(dexEntry = dexEntry)
)
}
val newPackList: MutableList<PackEntry> = mutableListOf()
for (packEntry in _uiState.value.packs) {
newPackList.add(
calcRarity(packEntry = packEntry)
)
}
_uiState.update { currentState ->
currentState.copy(packs = newPackList, dex = newDexList)
}
Log.d(TAG, "Finished loading")
}
private fun calcRarity(packEntry: PackEntry): PackEntry {
val packId = packEntry.id
var totalDiamonds = 0
var collectedDiamonds = 0
var totalStars = 0
var collectedStars = 0
for (card in _uiState.value.dex) {
if (packId in card.packIds) {
if (card.rarity >= 10) {
totalStars ++
if (card.isActive) {collectedStars ++}
} else {
totalDiamonds ++
if (card.isActive) {collectedDiamonds ++}
}
}
}
packEntry.totalStar = totalStars
packEntry.totalDiamond = totalDiamonds
packEntry.collectedStar = collectedStars
packEntry.collectedDiamond = collectedDiamonds
Log.d(TAG, "Calculated rarity")
return packEntry
}
private fun checkActive(dexEntry: DexEntry): DexEntry {
return dexEntry.copy(isActive = dexEntry.numberPossession > 0)
}
fun toggleEntry(cardId: Int) {
val newDex = _uiState.value.dex
val cardIndex = newDex.indexOfFirst { it.cardId == cardId } //-1 if no item was found
if (cardIndex == -1) {
return
}
val newCard = newDex[cardIndex]
newCard.isActive = !newCard.isActive
newDex[cardIndex] = newCard
_uiState.update { currentState ->
currentState.copy(dex = newDex)
}
Log.d(TAG, "Updated _uiState")
val newPacks = _uiState.value.packs
for (packId in newCard.packIds) {
val packIndex = _uiState.value.packs.indexOfFirst { it.id == packId }
if (packIndex == -1){
Log.d(TAG, "Could not find Pack with ID: $packId")
} else {
newPacks[packIndex] = calcRarity(newPacks[packIndex])
}
}
_uiState.update { currentState ->
currentState.copy(packs = newPacks)
}
}
init {
load()
}
}
In the Logs can see that calcRarity() is called, so in toggle Entry the Packs should be updated. But I can not see any updates on the screen.toggle Entry is called from another Screen (DexScreen). On this Screen the values of packEntry.collectedStar and packEntry.collectedDiamond is also not updated.
If you need the whole code, you can find it here. I tried it with diffrent methods like passing through the viewModel or calling by remember or assigning the variable by collect as StateFlow, but nothing seems to work.
Does anybody have an idea, what went wrong? Its my first real Android Project and the smaller ones all worked as I expected.
Best regards
本文标签: Android Compose UiState not updatedStack Overflow
版权声明:本文标题:Android Compose UiState not updated - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742096366a2420572.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论