'how to avoid repeatOnLifecycle excute again and again when fragment resume
how can I avoid the collect{} code execute again when navigate back to the fragment.
ViewModel class
private val _commitResult = MutableStateFlow<Map<String, Any>>(mapOf())
val commitResult: StateFlow<Map<String, Any>> = _commitResult
Fragment code like this:
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED){
viewModel.commitResult.collect { data ->
Logger.i("commitResult $data")
//navigate to another fragment
}
}
}
when I change the _commitResult value in viewModel first, jump to another fragment works fine.
unfortunately, when I go back to the fragment. collect{ // navigate to another fragment}
will
excute again.
I know when back to the fragment. onCreateView excute again and viewModel will emit the data store
before, so thecollect { // navigate to another fragment}
excute. How can I avoid this?
same as LiveData, I use Event to fix this with LiveData.
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
how can I handle this with stateflow? actually I don't like Event<.> to handle this, am I use the stateflow in a wrong way? how I can fix this? If anyone who can help, thanks in advance.
Solution 1:[1]
StateFlow keeps it's state, so I'd suggest either:
A) Use SharedFlow
. https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-shared-flow/
B) Use a pattern where you handle the dismissal of events
class Vm: ViewModel() {
private val mEvent = MutableStateFlow<MyResult?>(null)
val event = mEvent.asStateFlow()
fun dismissEvent() {
mEvent.value = null
}
}
class Frag: Fragment() {
override fun onViewCreated() {
vm.event.collect {
navigate()
vm.dismissEvent()
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | vpuonti |