I need to broadcast events from different places within my app, and I need these events to be listened by different ViewModels. What I did is that I created a "custom" implementation of EventBus using Kotlin Coroutines, Channel more specifically. The implementation looks like this:
interface FlowEventBus {
sealed class MessageEvent {
data class MessageA(
val someData: Int
) : MessageEvent()
data class MessageB(
val someOtherData: String
) : MessageEvent()
object MessageC : MessageEvent()
}
suspend fun postMessage(messageEvent: MessageEvent)
fun flowMessage(): Flow<MessageEvent>
}
class FlowEventBusImpl() : FlowEventBus {
private val channel = Channel<FlowEventBus.MessageEvent>()
override suspend fun postMessage(messageEvent: FlowEventBus.MessageEvent) {
channel.send(messageEvent)
}
override fun flowMessage(): Flow<FlowEventBus.MessageEvent> {
return channel.receiveAsFlow()
}
}
Then in my ViewModels I use it like this
@HiltViewModel
class SomeViewModel @Inject constructor(
private val flowEventBus: FlowEventBus
) : ViewModel() {
val message = flowEventBus.flowMessage().asLiveData()
// ...
The idea is that whatever Activity or Fragment is using this ViewModel, they can observe the message property and react to the "EventBus" events.
What's the problem?
Some of these events are unreliable. For example, let's say ActivityA is observing messages and it prompts a Snackbar every time we get a MessageC event. If the FlowEventBus broadcasts a MessageC event twice we'd only see the Snackbar pop once.
I'm not very savvy about Kotlin Coroutines yet, what I think might be happening is the classing SingleLiveEvent scenario. My guess is that the asLiveData() extension turns the Flow into a MutableLiveData and if we set the same value twice, it will just ignore it. But I'm not sure how to introduce SingleLiveEvent here.
Any feedback is welcome, Thanks!