Android Compose UiState не обновленAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Android Compose UiState не обновлен

Сообщение Anonymous »

У меня проблема с Android Compose. Он не отслеживает состояние некоторых переменных, как я ожидал. По сути, он вообще не отслеживает, а иногда и не в реальном времени, что изменилось. Я делаю следующее:
В моем NavHost или, лучше сказать, прежде чем я определяю uiState, помните:

Код: Выделить всё

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
)
}
После этого в моем СтатистикаScrren:

Код: Выделить всё

    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
)
}
}
}
Поэтому я беру значения uiState (ранее я пробовал это, определяя uiState вStatisticScreen, а также в NavHost, но это ничего не меняет.
/>Я обновляю состояние в ViewModel, определенное следующим образом:

Код: Выделить всё

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 =
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  = mutableListOf()
for (dexEntry in _uiState.value.dex) {
//Log.d(TAG, "Starting searching Dex")
newDexList.add(
checkActive(dexEntry = dexEntry)
)
}

val newPackList: MutableList
 = mutableListOf()
for (packEntry in _uiState.value.packs) {
newPackList.add(
calcRarity(packEntry = packEntry)
)
}
_uiState.update { currentState ->
currentState.copy(packs = newPackList, dex = newDexList)
}
}
}

val newDexList : MutableList = mutableListOf()
for (dexEntry in _uiState.value.dex) {
newDexList.add(
checkActive(dexEntry = dexEntry)
)
}

val newPackList: MutableList = 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()
}
}
В журналах видно, что вызывается CalcRarity(), поэтому при переключении Entry пакеты должны быть обновлены. Но я не вижу никаких обновлений на экране. toggle Вход вызывается с другого экрана (DexScreen). На этом экране значения packageEntry.collectedStar и packageEntry.collectedDiamond также не обновляются.
Если вам нужен весь код, вы можете найти его здесь. Я пробовал это с помощью разных методов, таких как передача через viewModel или вызов по памяти или присвоение переменной с помощью сбора как StateFlow, но, похоже, ничего не работает.
Есть ли у кого-нибудь идеи, что пошло не так? ? Это мой первый настоящий Android-проект, и все более мелкие проекты работали так, как я ожидал.
С уважением

Подробнее здесь: https://stackoverflow.com/questions/793 ... ot-updated
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»