Skip to content

Instantly share code, notes, and snippets.

@gmk57
Last active September 26, 2024 17:17
Show Gist options
  • Save gmk57/330a7d214f5d710811c6b5ce27ceedaa to your computer and use it in GitHub Desktop.
Save gmk57/330a7d214f5d710811c6b5ce27ceedaa to your computer and use it in GitHub Desktop.
Sending events to UI with Channel/Flow + custom collector (see my first comment for reasons behind it)
/**
* Starts collecting a flow when the lifecycle is started, and **cancels** the collection on stop.
* This is different from `lifecycleScope.launchWhenStarted { flow.collect{...} }`, in which case
* the coroutine is just suspended on stop.
*/
inline fun <reified T> Flow<T>.collectWhileStarted(
lifecycleOwner: LifecycleOwner,
noinline action: suspend (T) -> Unit
) {
object : DefaultLifecycleObserver {
private var job: Job? = null
init {
lifecycleOwner.lifecycle.addObserver(this)
}
override fun onStart(owner: LifecycleOwner) {
job = owner.lifecycleScope.launch {
collect { action(it) }
}
}
override fun onStop(owner: LifecycleOwner) {
job?.cancel()
job = null
}
}
}
class MyViewModel : ViewModel() {
// You can specify exact buffer size and onBufferOverflow strategy here, or go full blast with Channel.UNLIMITED
private val eventChannel = Channel<String>(capacity = 10, onBufferOverflow = BufferOverflow.DROP_OLDEST)
val eventFlow = eventChannel.receiveAsFlow()
fun sendEvent(element: String) = eventChannel.trySend(element) // `trySend` replaces `offer` since Coroutines 1.5
}
class MyFragment : Fragment(R.layout.fragment_my) {
private val viewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// You can collect flow in `onCreate` using `this` as lifecycleOwner
// This is a bit more efficient: `LifecycleObserver` is registered only once
viewModel.eventFlow.collectWhileStarted(this) { Log.i(TAG, "event: $it") }
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Or you can collect flow in `onViewCreated` using `viewLifecycleOwner`
// This more closely resembles a typical LiveData observer
viewModel.eventFlow.collectWhileStarted(viewLifecycleOwner) { Log.i(TAG, "event: $it") }
}
}
@itstanany
Copy link

BTW, one phrase caught my eye: "business logic remains the same for the same app on different mobile platforms". Is Google starting to push us towards KMP? ;)

In 2024, your expectations are materializing.

https://android-developers.googleblog.com/2024/05/android-support-for-kotlin-multiplatform-to-share-business-logic-across-mobile-web-server-desktop.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment