Jetpack Compose卡片状态不同步及返回页面不重组问题求助
问题描述

所有爱心图标状态本应保持同步,但返回选餐页面时,卡片并未发生重组(尽管日志显示已执行重组操作)。若返回主页面后重新进入选餐页面,则卡片可正常重组。
尝试将状态移至卡片组件外部,但无法在卡片内部修改该状态。
相关代码
ViewModel
data class SelectMealUiState( val meals: List<Meal> = listOf() ) class SelectMealViewModel( mealsRepository: IMealsRepository, firebaseAuth: FirebaseAuth ) : MealViewModel(mealsRepository, firebaseAuth = firebaseAuth) { private var _selectMealUiState: MutableStateFlow<SelectMealUiState> = MutableStateFlow(SelectMealUiState()) val selectMealUiState: StateFlow<SelectMealUiState> get() = _selectMealUiState.asStateFlow() fun updateState(category: String) { viewModelScope.coroutineContext.cancelChildren() viewModelScope.launch(dispatcherIo) { mealsRepository.getAllLocalMealsByCategoryFlow(category).collect { _selectMealUiState.update { currentState -> currentState.copy(meals = it) } } } } }
Screen
const val TAG = "SelectMealScreen" @Composable fun SelectMealScreen( categoryName: String, viewModelSelectMeal: SelectMealViewModel = viewModel(factory = AppViewModelProvider.Factory), viewModelAuth: AuthViewModel = viewModel(factory = AppViewModelProvider.Factory), navController: NavController, refreshCallback : () -> Unit, favoriteCallback: () -> Unit, loginRegisterCallback: () -> Unit, isBackEnabled: Boolean, navBack: () -> Unit, modifier : Modifier = Modifier ) { val selectMealUiState by viewModelSelectMeal.selectMealUiState.collectAsState() val firebaseAuth: FirebaseAuth by lazy { FirebaseAuth.getInstance() } val isUserLoggedIn by remember { mutableStateOf(firebaseAuth.currentUser != null) } LaunchedEffect(true) { Log.d(TAG, "update state meals selection screen") viewModelSelectMeal.updateState(categoryName) } Log.d(TAG, "Recomposition! isUserLoggedIn: $isUserLoggedIn") Scaffold( topBar = { TopBar( favoriteCallback = favoriteCallback, refreshCallback = refreshCallback, userCallback = loginRegisterCallback, isBackEnabled = isBackEnabled, backCallBack = navBack ) }, modifier = Modifier.fillMaxSize() ) { innerPadding -> Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier .fillMaxSize() .padding(innerPadding) ) { Text(text = categoryName, fontSize = 30.sp, modifier = Modifier.padding(vertical = 10.dp)) MealsGrid( mealsList = selectMealUiState.meals, navController = navController, isUserLoggedIn = isUserLoggedIn, viewModelSelectMeal = viewModelSelectMeal ) } } } @Composable fun MealsGrid( mealsList: List<Meal>, navController: NavController, viewModelSelectMeal: SelectMealViewModel, isUserLoggedIn: Boolean ) { LazyVerticalGrid( columns = GridCells.Fixed(2), contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp), verticalArrangement = Arrangement.spacedBy(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp) ) { // TODO gestisci caso in cui non ci sono elementi in memoria items(mealsList, key = { meal -> meal.idMeal }) { meal -> MealsCard( meal = meal, setfavoriteCallBack = { if (isUserLoggedIn) { viewModelSelectMeal.uploadOnRemoteAndSetLocally(mealId = meal.idMeal) } else { viewModelSelectMeal.setLocalMealAsFavorite(meal.idMeal); } Log.d(TAG, "Card set heart icon callback ${this.hashCode()}") }, unsetfavoriteCallBack = { if (isUserLoggedIn) { viewModelSelectMeal.removeFromRemoteAndUnsetLocally(mealId = meal.idMeal) } else { viewModelSelectMeal.unsetLocalMealAsFavorite(meal.idMeal) } Log.d(TAG, "Card unset heart icon callback $this.hashcode") }, onClickCallback = { navController.navigate("Detail" + "/" + meal.idMeal) } ) } } } @Composable fun MealsCard( meal: Meal, setfavoriteCallBack: () -> Unit, unsetfavoriteCallBack: () -> Unit, onClickCallback: () -> Unit ) { ElevatedCard( elevation = CardDefaults.cardElevation( defaultElevation = 6.dp ), onClick = onClickCallback, shape = MaterialTheme.shapes.medium, modifier = Modifier.height(210.dp) ) { var isMealFlaggedAsFavorite by rememberSaveable { mutableStateOf(meal.isFavorite) } Log.d(TAG, "recomposition, favorite state of the card ${meal.idMeal} $isMealFlaggedAsFavorite" ) Column { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth() ) { Box(modifier = Modifier.width(120.dp)){ Text(meal.strMeal) } Box(modifier = Modifier.width(20.dp)) { val unsetAndChangeHeart: () -> Unit = { unsetfavoriteCallBack() isMealFlaggedAsFavorite = "0" } val setAndChangeHeart: () -> Unit = { setfavoriteCallBack() isMealFlaggedAsFavorite = "1" } if(isMealFlaggedAsFavorite == "1") { IconButton(onClick = unsetAndChangeHeart ) { Icon( imageVector = Icons.Filled.Favorite, contentDescription = "" ) } } else { IconButton(onClick = setAndChangeHeart) { Icon( imageVector = Icons.Outlined.FavoriteBorder, contentDescription = "" ) } } } } Box{ AsyncImage( model = meal.strMealThumb, contentDescription = "", error = painterResource(R.drawable.ic_broken_image), placeholder = painterResource(R.drawable.loading_img), contentScale = ContentScale.Crop ) } } } }
内容的提问来源于stack exchange,提问作者Max Max
相关产品推荐
相关产品推荐

