Event Bus Pattern in Android Using Kotlin Flows
Tags: android, flow, kotlin, event
Published: 2022-12-25 10:35:10

---
title: Event Bus Pattern in Android Using Kotlin Flows
published: true
description: Publish an event using shared flow and subscribe to it from anywhere.
tags: #android, #flow, #kotlin, #event
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wsufjxdszig7ad4ql43u.png


# Use a ratio of 100:42 for best results.
# published_at: 2022-12-24 17:24 +0000
---

The event bus design pattern is very popular and advantageous in programming. The publishers trigger events and subscribers can listen to those events from anywhere. It reduces unnecessary coupling. With the arrival of observers and other frameworks, this design pattern is in less use nowadays. To achieve broadcasting of events in Android, we already had the following options:
- RxBus
- Local Broadcast
- Third parties i.e. green robot etc.

While Kotlin is gaining popularity, language is providing so many cutting-edge frameworks. Flow is one of them. Kotlin released a stable version of StateFlow and SharedFlow with the language's 1.4 release. We can achieve the EventBus design pattern using SharedFlow and leverage the benefits of language and framework.

## Implementation
You can achieve event bus using shared flow using following easy steps:

### Step 1:

Create a generic event bus class as follows:

```kotlin
object EventBus {
  private val _events = MutableSharedFlow<Any>()
  val events = _events.asSharedFlow()

  suspend fun publish(event: Any) {
    _events.emit(event)
  }

  suspend inline fun <reified T> subscribe(crossinline onEvent: (T) -> Unit) {
    events.filterIsInstance<T>()
      .collectLatest { event ->
        coroutineContext.ensureActive()
        onEvent(event)
      }
  }
}
```

Here, the `publish` method posts an event passed as a parameter. Subscribe method collects those events. It does some utility work i.e. filtering correct event, ensuring coroutine context is active or not then providing event on the `onEvent()` method. Moreover, you can collect public `events` shared flow variable to apply custom logic if needed.


![Event Bus Flow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okhn6erafi3pvotos1ng.png)


### Step 2:
Create an event class as follows:

```kotlin
data class LoginEvent(
  val userId: String,
  val userName: String
)
```
Ideally, your event classes would be data classes as in any event, you would require some data. But it could be any kind of class.

### Step 3:
Now use those methods to publish and subscribe to events. Creating a separate class would be preferred as per module or feature. One example is as follows:

```kotlin
class LoginEventHandler {
  suspend fun postLoginEvent(loginEvent: LoginEvent) {
    EventBus.publish(loginEvent)
  }

  fun subscribeLoginEvent(lifecycleOwner: LifecycleOwner) {
    lifecycleOwner.lifecycleScope.launch {
      EventBus.subscribe<LoginEvent> { loginEvent ->
        Log.d("LoginEventHandler", "${loginEvent.userName} logged-in successfully")
      }
    }
  }
}
```

And that's it!!!  


## Conclusion
Event bus has been a debatable topic among developers. Some say it should not be followed because it could act as a single point of failure. Sometimes, it could be hard to debug what is the source of the event. 
   However, it is widely accepted and useful for many use cases i.e. updating UI on internet connectivity changes, refreshing UI on login once login popup dismisses i.e. in e-commerce apps, etc. In my opinion, don't be too dependent on it. Use it as minimally as possible. Your opinion and approaches are welcome in the comments. 

You can check my articles on [Medium](https://medium.com/@mohitrajput987) also.