1

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
 )
Mehmet Gür
  • 503
  • 7
  • 20

2 Answers2

1

You could try forcing the state to get updated by creating a new instance of calendar and setting it to the MutableStateFlow

Something like this

    fun setSelectedStartDate(currentCalendar: Calendar) {
         val myCalendar = Calendar.getInstance()
         myCalendar.set(Calendar.YEAR, currentCalendar.get(Calendar.YEAR))
         myCalendar.set(Calendar.MONTH, currentCalendar.get(Calendar.MONTH))
         myCalendar.set(Calendar.DAY_OF_MONTH, 
         currentCalendar.get(Calendar.DAY_OF_MONTH))
         _selectedStartDate.value = myCalendar
}
StormSpirite
  • 110
  • 7
  • thanks, I tried, it updates stateFlow but it also sets the time(to current time) because of Calendar.getInstance(). We need to set only date fields – Mehmet Gür Feb 23 '23 at 09:23
  • try applying updated only on the desired fields val myCalendar = Calendar.getInstance().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)) } – StormSpirite Feb 23 '23 at 09:34
  • it still resets the time unfortunately. – – Mehmet Gür Feb 23 '23 at 14:02
1

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
Mehmet Gür
  • 503
  • 7
  • 20