I have written an article stating the reasons why LocalBroadcastManager is deprecated, read here. And I have suggested multiple solutions among which EventBus is one. Here we will learn EventBus the LocalBroadcastManager alternative.
Quick Navigation
What is EventBus ?
EventBus is a simple library which works as a replacement for LocalBroadcastManager. It is created by greenrobot, on GitHub. It works in the principle of publish / subscribe.
The working of the library is really very simple. There are subscribers for certain type of events and when the publisher dispatches a Event. The subscribers automatically get notified with the latest data.
That was a simple introduction to EventBus let us see how we can use it in our application. It is really very easy and hassle free.
Including the dependency for EventBus
Just add the following line in the dependencies { }
block of your app > build.gradle
file. And sync your project with gradle. You’re all set to use the library
// event bus dependency
implementation 'org.greenrobot:eventbus:3.2.0'
Code language: JavaScript (javascript)
Using EventBus as LocalBroadcastManager Alternative
Let us break down the steps into 3 simple steps.
- Creating events
- Subscribing to events
- Sending broadcasts to event
Creating events
Let us see how we can create events.
Are you familiar with the term Plain Old Java Objects (POJO) . If not do not worry they are just simple classes for holding data and nothing more. They should not contain any business logic in them.
Create a simple data class
with name SimpleEvent
for our POJO equivalent.
data class SimpleEvent(var data: String)
Code language: Kotlin (kotlin)
Modify the variables in the class as you wish. For the sake of simplicity I have only used a String
type with identifier data
.
Now that we have made the Event ready let us move to registering and unregistering.
Subscribing to Events
Once we are done creating the Event let us subscribe to the event. This is a two step process. We have to register
and unregister
just like in LocalBroadcastManager.
The main difference from LocalBroadcastManager
is that EventBus
does not require any context
object.
Here let us register in our onStart() { }
method of our Activity
.
override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
}
Code language: Kotlin (kotlin)
You can do this wherever you want. Just make sure to invoke this line EventBus.getDefault().register(this)
before posting anything from EventBus.
And if you want to no longer receive updates call this method in your onStop() { }
block of activity or when you want to stop receiving new data.
override fun onStop() {
super.onStop()
EventBus.getDefault().unregister(this)
}
Code language: Kotlin (kotlin)
Now that we have registered and unregistered there is one more thing left to do.
Let us define the method that will be invoked once we have new data. It will have the data we will be sending later.
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventReceived(event: SimpleEvent) {
Log.d("MainActivity", "we have this : ${event.data}")
}
Code language: JavaScript (javascript)
More on @Subscribe
annotation is provided below, keep reading.
That is it let us finally see how we can send events to all our subscribers.
Posting Events to Subscribers
Now this is the easiest part of code yet. From where you want to send the data just do this:
EventBus.getDefault().post(SimpleEvent("sending @ ${System.currentTimeMillis()}"))
Code language: Kotlin (kotlin)
We have sent new instance of SimpleEvent
and invoked the .post()
method.
That is all you need to do to make it work. If you run the code it should work. I have a simple Activity which has the final code as:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val service = Executors.newSingleThreadExecutor()
service.submit {
while (true) {
Thread.sleep(2_000)
EventBus.getDefault().post(SimpleEvent("sending @ ${System.currentTimeMillis()}"))
}
}
}
override fun onStart() {
super.onStart()
EventBus.getDefault().register(this)
}
override fun onStop() {
super.onStop()
EventBus.getDefault().unregister(this)
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventReceived(event: SimpleEvent) {
Log.d("MainActivity", "we have this : ${event.data}")
}
}
Code language: Kotlin (kotlin)
I have sent current time every 2 seconds from another thread. Want to know why I used ExecutorService
? Read: Async Task in Android is Deprecated: There are Better Ways
More on @Subscribe
annotation
If you are new to EventBus you might be wondering what that strange @Subscribe
does. It is called an annotation. I will surely write more about it on upcoming articles.
In EventBus there is ThreadMode
enum
class which has multiple properties. We have used ThreadMode.MAIN
. What does it do though ?
The annotation makes sure that the method is invoked in specified thread. Everything you see runs on UI thread in Android. But if you try to execute long running tasks the UI might become unresponsive.
So once you complete the processing on background thread. You can send back the result and it invoke the method in specified thread.