В моем 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
)
}
Код: Выделить всё
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
)
}
}
}
/>Я обновляю состояние в 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()
}
}
Если вам нужен весь код, вы можете найти его здесь. Я пробовал это с помощью разных методов, таких как передача через viewModel или вызов по памяти или присвоение переменной с помощью сбора как StateFlow, но, похоже, ничего не работает.
Есть ли у кого-нибудь идеи, что пошло не так? ? Это мой первый настоящий Android-проект, и все более мелкие проекты работали так, как я ожидал.
С уважением
Подробнее здесь: https://stackoverflow.com/questions/793 ... ot-updated
Мобильная версия