androidandroid-jetpack-composeandroid-calendarkotlin-stateflow

Jetpack Compose - StateFlow not updating when setting the value


I'm using StateFlow to update compose views. There is a stateFlow that type is Calendar;

private val _selectedStartDate: MutableStateFlow<Calendar> = MutableStateFlow(Calendar.getInstance())
val selectedStartDate: StateFlow<Calendar>
    get() = _selectedStartDate

I need to update only year, month and day of this calendar(not the time). I tried like this;

 fun setSelectedStartDate(currentCalendar: Calendar) {
     _selectedStartDate.value = _selectedStartDate.value.apply {
         set(Calendar.YEAR, currentCalendar.get(Calendar.YEAR))
         set(Calendar.MONTH, currentCalendar.get(Calendar.MONTH))
         set(Calendar.DAY_OF_MONTH, currentCalendar.get(Calendar.DAY_OF_MONTH))
     }
}

But this is not updating the compose view when calling this function. I guess it's because we're not assigning a new value to mutableStateFlow. Because when assigning the currentCalendar to _selectedStartDate the problem is solving but it also sets the time. But I need to only modify year, month and day. So how it can be fixed?

In the UI it's implemented with this way;

 val selectedDate = viewModel.selectedStartDate.collectAsState()
 OutlinedTextView(
       ...
     text = selectedDate.value.time
 )

Solution

  • So the problem is like I expected, not chancing of the value of stateFlow. So stateFlow is not aware if it's updated since it's reference didn't change. It's close to @StromSpirite answer but to save the times we also should hande the hour and minute. So this is worked;

    val newDate = Calendar.getInstance()
        newDate.apply {
            set(Calendar.YEAR, currentCalendar.get(Calendar.YEAR))
            set(Calendar.MONTH, currentCalendar.get(Calendar.MONTH))
            set(Calendar.DAY_OF_MONTH, currentCalendar.get(Calendar.DAY_OF_MONTH))
            set(Calendar.HOUR_OF_DAY, selectedStartDate.value.get(Calendar.HOUR_OF_DAY))
            set(Calendar.MINUTE, selectedStartDate.value.get(Calendar.MINUTE))
        }
        _selectedStartDate.value = newDate