11package com.hoc081098.channeleventbus.sample.android.common
22
33import androidx.annotation.MainThread
4- import com.hoc081098.channeleventbus.sample.android.BuildConfig
4+ import androidx.lifecycle.ViewModel
55import java.io.Closeable
66import java.lang.System.identityHashCode
77import kotlin.LazyThreadSafetyMode.NONE
@@ -10,11 +10,22 @@ import kotlinx.coroutines.channels.onClosed
1010import kotlinx.coroutines.channels.onFailure
1111import kotlinx.coroutines.channels.onSuccess
1212import kotlinx.coroutines.flow.Flow
13+ import kotlinx.coroutines.flow.FlowCollector
1314import kotlinx.coroutines.flow.emitAll
14- import kotlinx.coroutines.flow.flow
1515import kotlinx.coroutines.flow.receiveAsFlow
1616import timber.log.Timber
1717
18+ sealed interface SingleEventFlow <E > : Flow <E > {
19+ /* *
20+ * Must collect in [Dispatchers.Main.immediate][kotlinx.coroutines.MainCoroutineDispatcher.immediate].
21+ * Safe to call in the coroutines launched by [androidx.lifecycle.lifecycleScope].
22+ *
23+ * In Compose, we can use [CollectWithLifecycleEffect] with `inImmediateMain = true`.
24+ */
25+ @MainThread
26+ override suspend fun collect (collector : FlowCollector <E >)
27+ }
28+
1829@MainThread
1930interface HasSingleEventFlow <E > {
2031 /* *
@@ -23,7 +34,7 @@ interface HasSingleEventFlow<E> {
2334 *
2435 * In Compose, we can use [CollectWithLifecycleEffect] with `inImmediateMain = true`.
2536 */
26- val singleEventFlow: Flow <E >
37+ val singleEventFlow: SingleEventFlow <E >
2738}
2839
2940@MainThread
@@ -35,23 +46,21 @@ sealed interface SingleEventFlowSender<E> {
3546 suspend fun sendEvent (event : E )
3647}
3748
49+ private class SingleEventFlowImpl <E >(private val channel : Channel <E >) : SingleEventFlow<E> {
50+ override suspend fun collect (collector : FlowCollector <E >) {
51+ debugCheckImmediateMainDispatcher()
52+ return collector.emitAll(channel.receiveAsFlow())
53+ }
54+ }
55+
3856@MainThread
3957class SingleEventChannel <E > :
4058 Closeable ,
4159 HasSingleEventFlow <E >,
4260 SingleEventFlowSender <E > {
4361 private val _eventChannel = Channel <E >(Channel .UNLIMITED )
4462
45- override val singleEventFlow: Flow <E > by lazy(NONE ) {
46- if (BuildConfig .DEBUG ) {
47- flow {
48- debugCheckImmediateMainDispatcher()
49- emitAll(_eventChannel .receiveAsFlow())
50- }
51- } else {
52- _eventChannel .receiveAsFlow()
53- }
54- }
63+ override val singleEventFlow: SingleEventFlow <E > by lazy(NONE ) { SingleEventFlowImpl (_eventChannel ) }
5564
5665 init {
5766 Timber .d(" [EventChannel] created: hashCode=${identityHashCode(this )} " )
@@ -78,3 +87,7 @@ class SingleEventChannel<E> :
7887 Timber .d(" [EventChannel] closed: hashCode=${identityHashCode(this )} " )
7988 }
8089}
90+
91+ @Suppress(" NOTHING_TO_INLINE" )
92+ inline fun <E > SingleEventChannel<E>.addToViewModel (viewModel : ViewModel ) =
93+ apply { viewModel.addCloseable(this ) }
0 commit comments