MutableStateFlow doesn't update UI automatically in kotlin compose?

233 views Asked by At

In Kotlin Jetpack Compose, I have a list called meals on the viewmodel side and I want to add an alternative food selected by the user to this list. For example, there are 10 foods in the meals list and the user wants to replace the apple food with one of its alternatives, for example, with pear. When the user presses pear. From time to time, he needs to find the apple in his meal list and replace it with a pea but unless I make a change to recompose the UI side, the change I make does not appear on the UI side. So even if I change the apple to pear, the UI is not automatically updated? why ? I couldn't find where I was making a mistake. Doesn't MutableStateFlow automatically find the changes and update the UI side?

UI:

ModalBottomSheetLayout(
        sheetShape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp),
        sheetState = bottomSheetState,
        sheetContent = {
            BaseBottomSheet(
                content = {
                    when{
                        isClickDelete -> {
                          
                        }
                        isClickAlternative -> {
                            AlternativeMeals(
                                foodName = alternativeMealName,
                                unitName = alternativeMealUnitName ,
                                alternativeList = state.alternativeList,
                                onClick = { alternativeMeal ->
                                    if(mealId != null && mealToBeChangeDpaId != null){
                                        addAlternativeItemToMealList(mealToBeChangeDpaId!!,mealId!!,alternativeMeal,state.meals)
                                    }

                                    scope.launch {
                                        bottomSheetState.hide()
                                    }
                                })
                        }
                    }
 

viewmodel:

    private val _state = MutableStateFlow(MyDietPlanScreenState())
    val state: StateFlow<MyDietPlanScreenState> = _state.asStateFlow()

    fun addAlternativeItemToMealList(
            dpaId: Int,
            mealId: Int,
            alternativeItem: MealItemUIModel,
            meals: ArrayList<Meals>
        ) {
    
            val newMeals = ArrayList(meals)
            val mealToBeChanged = newMeals.find { it.mealId == mealId }
    
            mealToBeChanged?.let { meal ->
    
                val foodIndexToReplace = meal.foods.indexOfFirst { it.dpaId == dpaId }
    
                if (foodIndexToReplace != -1) {
    
                    meal.foods[foodIndexToReplace] = Foods(
                        defaultAmount = alternativeItem.defaultAmount,
                        unitName = alternativeItem.unitName,
                        nutritionCarbohydrt = alternativeItem.nutritionCarbohydrt,
                        isFood = alternativeItem.isFood,
                        image = alternativeItem.image,
                        nutritionFat = alternativeItem.nutritionFat,
                        addedFrom = alternativeItem.addedFrom,
                        dpaId = alternativeItem.dpaId,
                        nutritionId = alternativeItem.nutritionId,
                        nutritionProtein = alternativeItem.nutritionProtein,
                        unitId = alternativeItem.unitId,
                        value = alternativeItem.value,
                        amount = alternativeItem.amount?.toInt(),
                        isFavorited = alternativeItem.isFavorited,
                        isChecked = alternativeItem.isChecked,
                        nutritionName = alternativeItem.nutritionName,
                        kcal = alternativeItem.kcal
                    )
                }
            }
    
            _state.value = _state.value.copy(meals = newMeals) 
        }
 data class MyDietPlanScreenState(
        val meals: ArrayList<Meals> = arrayListOf(),
        val alternativeList: ArrayList<MealItemUIModel> = arrayListOf()
      ...
    )

example json data :

 "meals": [
            {
                "meal_image": "",
                "foods": [
                    {
                        "dpa_id": 71,
                        "nutrition_name": "egg",
                    },
                    {
                        "dpa_id": 72,
                        "nutrition_name": "bread",
                    }
                ],
                "meal_name": "breakfast",
                "meal_time": "08:02:00",
                "meal_id": 8,
                "kcal": "0/586"
            },

INFO

dpa_id -> special id for food  
meal_id -> specieal id for meal 
mealToBeChangeDpaId -> dpa_id of the food the user wants to change 
alternativeMeal -> alternative food choice
1

There are 1 answers

0
Mercan Birer On
  private val _state = MutableStateFlow<MutableList<MyDietPlanScreenState>>(mutableStateListOf())
  val state: StateFlow<List<MyDietPlanScreenState>> = _state

Can you try this way?