Skip to content

Instantly share code, notes, and snippets.

@fergusonm
Last active March 9, 2021 19:20
Show Gist options
  • Save fergusonm/ca387b98cd17eba3073df24529c46a85 to your computer and use it in GitHub Desktop.
Save fergusonm/ca387b98cd17eba3073df24529c46a85 to your computer and use it in GitHub Desktop.
Conflated channel crashes
package com.example.launchwhendemo.ui.main
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.navigation.fragment.findNavController
import com.example.launchwhendemo.R
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import observeIn
class MainFragment : Fragment(R.layout.main_fragment) {
private lateinit var viewModel: MainViewModel
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?
) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
view.findViewById<Button>(R.id.goButton).setOnClickListener { viewModel.go() }
viewModel.events
.onEach {
when(it) {
is MainViewModel.Event.A -> {
delay(500L) // for random reasons
val directions = MainFragmentDirections.actionMainFragmentToAFragment()
findNavController().navigate(directions)
}
MainViewModel.Event.B -> {
val directions = MainFragmentDirections.actionMainFragmentToBFragment()
findNavController().navigate(directions)
}
}
}
.observeIn(viewLifecycleOwner)
}
}
class MainViewModel : ViewModel() {
sealed class Event {
object A: Event()
object B: Event()
}
private val _eventChannel = Channel<Event>(Channel.CONFLATED)
val events = _eventChannel.receiveAsFlow()
fun go() {
// Simulate two navigation events being sent more or less simultaneously,
// one as a response to user action and another as a response to something else, say a slow web service
viewModelScope.launch {
_eventChannel.send(Event.A)
}
viewModelScope.launch {
_eventChannel.send(Event.B)
}
}
}
class AFragment : Fragment(R.layout.fragment_a) {}
class BFragment : Fragment(R.layout.fragment_b) {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment