Skip to content

hoc081098/DemoCoroutinesChannelResult

Repository files navigation

DemoCoroutinesChannelResult

Use Kotlinx Coroutines Channel to send and receive events between Fragments.

Hits

Overview

1. Create MainSingleEvent class.

sealed interface MainSingleEvent<out T : MainSingleEvent<T>> {
  interface Key<out T : MainSingleEvent<T>>

  val key: Key<T>

  data class HomeFragmentResult(val text: String) : MainSingleEvent<HomeFragmentResult> {
    override val key = HomeFragmentResult

    companion object : Key<HomeFragmentResult>
  }

  data class DashboardFragmentResult(val text: String) : MainSingleEvent<DashboardFragmentResult> {
    override val key = DashboardFragmentResult

    companion object : Key<DashboardFragmentResult>
  }

  data class HomeDetailsResult(val text: String) : MainSingleEvent<HomeDetailsResult> {
    override val key = HomeDetailsResult

    companion object : Key<HomeDetailsResult>
  }

  companion object {
    val KEYS: Set<Key<SomeMainSingleEvent>> = setOf(
      HomeFragmentResult,
      DashboardFragmentResult,
      HomeDetailsResult,
    )
  }
}

2. Create MainVM class with buffered channels as event bus.

class MainVM : ViewModel() {
  private val eventChannels: Map<MainSingleEvent.Key<SomeMainSingleEvent>, Channel<SomeMainSingleEvent>> =
    MainSingleEvent.KEYS.associateBy(
      keySelector = { it },
      valueTransform = { Channel<MainSingleEvent<SomeMainSingleEvent>>(Channel.UNLIMITED) }
    )

  fun <T : MainSingleEvent<T>> sendEvent(event: T) {
    checkNotNull(eventChannels[event.key]) { "Must register ${event.key} in MainSingleEvent.Companion.KEYS before using!" }
      .trySend(event)
      .getOrThrow()
      .also { Log.d("@@@", "Sent $event") }
  }

  @Suppress("UNCHECKED_CAST")
  fun <T : MainSingleEvent<T>, K : MainSingleEvent.Key<T>> receiveEventFlow(key: K): Flow<T> =
    checkNotNull(eventChannels[key]) { "Must register $key in MainSingleEvent.Companion.KEYS before using!" }
      .receiveAsFlow()
      .map { it as T }
}

3. Send and receive events in Fragments.

We will share MainVM instance between Fragments using Activity as owner.

private val mainVM by viewModels<MainVM>(
  ownerProducer = { requireActivity() }
)

// send in HomeFragment
mainVM.sendEvent(MainSingleEvent.HomeFragmentResult("Hello from HomeFragment"))

// receive in others
mainVM.receiveEventFlow(MainSingleEvent.HomeFragmentResult)
  .onEach { Log.d("###", "Received $it") }
  .launchIn(lifecycleScope)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy