Skip to content

Instantly share code, notes, and snippets.

@fergusonm
Last active October 28, 2023 20:01
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fergusonm/88a728eb543c7f6727a7cc473671befc to your computer and use it in GitHub Desktop.
Save fergusonm/88a728eb543c7f6727a7cc473671befc to your computer and use it in GitHub Desktop.
launchWhenX dropping events
class MainFragment : Fragment(R.layout.main_fragment) {
companion object {
fun newInstance() = MainFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
lifecycleScope.launchWhenStarted {
viewModel.flow.collect {
print("********** View: launch when started collector received $it in lifecycle state ")
println(lifecycle.currentState.name)
}
}
// Notify the view model of a lifecycle event just to cause
// emissions during different lifecycle states. In practice
// the view model will emit values down the flow
// without care to the observer's lifecycle state.
// This just forces the conditions
// necessary to demonstrate the issue.
lifecycle.addObserver(LifecycleEventObserver { source: LifecycleOwner, event: Lifecycle.Event ->
println("********** event: ${event.name}")
viewModel.lifecycleEvent(event.name)
}
)
}
}
class MainViewModel : ViewModel() {
private var counter = AtomicInteger(0)
private val channel = Channel<String>(Channel.BUFFERED)
val flow = channel.receiveAsFlow()
fun lifecycleEvent(eventName: String) {
viewModelScope.launch {
// Send the event name down the flow to make some traffic
val i = counter.getAndIncrement()
val event = "$eventName $i"
println("********** ViewModel: Emitting $event on the flows")
channel.send(event)
}
}
}
Note that if you run this you'll see the following logs:
********** event: ON_STOP
********** ViewModel: Emitting ON_STOP 4 on the flows
********** View: launch when started collector received ON_STOP 4 in lifecycle state CREATED
********** event: ON_DESTROY
********** ViewModel: Emitting ON_DESTROY 5 on the flows
********** event: ON_CREATE
********** ViewModel: Emitting ON_CREATE 6 on the flows
********** View: launch when started collector received ON_CREATE 6 in lifecycle state STARTED
Note the event forced out during ON_STOP was received in the CREATED lifecycle state. This makes sense as the observer is in on_stop. However, this could be bad if the event is a navigation event.
Also, note that the ON_DESTROY event that was forced out was dropped! That is, no observer collected it. This is really bad.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment