Cross-page communication is a common scenario, and EventBus is often used, but EventBus is not life-cycle aware and will call back when it receives a message, so LiveData soon followed. However, it has disadvantages, such as the inability to switch receiving threads. Now that SharedFlow is stable, is it possible to do a wave?

Hence the FlowEventBus

Common message bus comparison

Design concept

Learn how to migrate from LiveData to Kotlin data stream:

SharedFlow as event carrier:


  • Easy thread switching relies on coroutines
  • Sticky effects can be achieved through replay
  • Can be subscribed by multiple observers
  • No observer autoclear events do not cause backlogs

Lifecycle perception of the Lifecycle, to achieve controllable response time. It can not only be used for global events, but also for communication within a single page without being transmitted to other pages, such as internal communication within activities and fragments.

Dependent library version

The key is kotlinx-coroutines > 1.4.x and lifecycle- Runtime-ktx > 2.3.x


The events in the following examples are arbitrary classes, just names defined to distinguish events during testing

Event to send
PostEvent (AppScopeEvent("form TestFragment")) postEvent(Fragment,FragmentEvent("form ") TestFragment")) //Activity internal scope postEvent(requireActivity(),ActivityEvent("form TestFragment")) copies the code event to listen to // receive the Activity Scope event observeEvent<ActivityEvent>(Scope = requireActivity()) {... } observeEvent<FragmentEvent>(Scope = Fragment) {... } // Receive AppScope event observeEvent<AppScopeEvent> {... }Copy the code
ObserveEvent <GlobalEvent>(scope = coroutineScope) {... }Copy the code
Delay to send
PostEvent (CustomEvent(value = "Hello Word"),1000) Copy code thread switch observeEvent<ActivityEvent>( {... }Copy the code
Specifies the minimum life state that can be sensed
observeEvent<ActivityEvent>(minActiveState = Lifecycle.State.DESTROYED) {
Copy the code
Listen in a sticky way
observeEvent<GlobalEvent>(isSticky = true) {
Copy the code
Remove viscous events
Copy the code

The principle of

This functionality relies on SharedFlow and Lifecycle of Kotlin coroutines and is therefore very simple to implement.

Viscous event
MutableSharedFlow<Any>(replay = if (isSticky) 1 else 0, extraBufferCapacity = Int.MAX_VALUE)Copy the code
Life cycle perception
fun <T> LifecycleOwner.launchWhenStateAtLeast(
    minState: Lifecycle.State,
    block: suspend CoroutineScope.() -> T
) {
    lifecycleScope.launch {
        lifecycle.whenStateAtLeast(minState, block)
Copy the code
Switch threads

WhenStateAtLeast Since the block executed is in the main thread by default, manual thread switching is required:

lifecycleOwner.launchWhenStateAtLeast(minState) {
    flow.collect { value ->
        lifecycleOwner.lifecycleScope.launch(dispatcher) {
                onReceived.invoke(value as T)
Copy the code
Delay events
viewModelScope.launch {
Copy the code
In order to distribute

Flow itself is ordered

Global singleton

Use the global ViewModel, mainly because of the ViewModelScope, to avoid GlobalScope. If you want to communicate within a single page, use ActivityScope’s ViewModel instead:

object ApplicationScopeViewModelProvider : ViewModelStoreOwner {

    private val eventViewModelStore: ViewModelStore = ViewModelStore()

    override fun getViewModelStore(): ViewModelStore {
        return eventViewModelStore

    private val mApplicationProvider: ViewModelProvider by lazy {

    fun <T : ViewModel> getApplicationScopeViewModel(modelClass: Class<T>): T {
        return mApplicationProvider[modelClass]
Copy the code

There are two maps inside the ViewModel, sticky and non-sticky:

internal class EventBusViewModel : ViewModel() {

    private val eventFlows: HashMap<String, MutableSharedFlow<Any>> = HashMap()

    private val stickyEventFlows: HashMap<String, MutableSharedFlow<Any>> = HashMap()

Copy the code

Android Advanced Development System Advanced notes, the latest interview review notes PDF,My lot

At the end of the article

Your likes collection is the biggest encouragement to me! Welcome to follow me, share Android dry goods, exchange Android technology. If you have any comments or technical questions about this article, please leave a comment in the comments section.