Currently I have a ViewPager2
Fragment (as the start destination), which holds two child Fragments: ActiveOrderFragment
and CompletedOrderFragment
, they both have their own ViewModel
s to handle the api calls (to get the active orders and completed orders).
When the user clicks on the order item it will navigate to OrderEditorFragment
, and there is a "Set Item as Active/Completed" button, clicking on that will update the status of the order (just simply a PUT request), and go back to the ViewPager2
Fragment.
In order to notify & refresh ActiveOrderFragment
and CompletedOrderFragment
, I created a SharedFlow
in OrderViewModel
, which is a shared ViewModel
:
class OrderViewModel(application: Application) : AndroidViewModel(application) {
private val uiScope = viewModelScope
private val _isOrderStatusChanged = MutableSharedFlow<Boolean>(replay = 1)
val isOrderStatusChanged: SharedFlow<Boolean>
get() = _isOrderStatusChanged
fun updateIsOrderStatusChanged() = _isOrderStatusChanged.emit(uiScope, true)
}
Then I observe (collect) this SharedFlow
in onCreateView()
of ActiveOrderFragment
and CompletedOrderFragment
:
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
orderViewModel.isOrderStatusChanged.collect {
if (it) {
Log.v("xxx", "refreshed!")
viewModel.refreshActiveOrders() //similar in CompletedOrderFragment
}
}
}
}
Here comes the issue: when I changed the status and go back to the pages, they both get notified and refreshed. However, now I click on any order item to go to the editor page but do nothing, and go back, the collect{}
gets called again, which is not an expected behavior. How to prevent that? I guess that's relevant to the replay
property...
Some extra info:
what is means replay
MutableSharedFlow<Boolean>(replay = 0)
catch nothingMutableSharedFlow<Boolean>(replay = 1)
catch latest valueMutableSharedFlow<Boolean>(replay = 2)
catch latest 2 valueif you set _isOrderStatusChanged twice with diff value, you will find out.