The Android framework makes a large use of background tasks, in order to keep a high responsiveness of the application for a better user experience. In details, the main thread, also called UI thread, is responsible the handle user inputs, like a click on a button, screen scrolling, etc... If you overload the UI thread and it will not be able to give a response to the user within 5 seconds, your application will receive an Application Not Responding (ANR) dialog.
This does not look good, right? Here is what is happening.
The right way of processing the click is in a separate thread. For doing so, Android offers different methods. One of these is using the AsyncTask class. So what you can do is:
- button is clicked, then
- show the progress bar, then
- start the AsyncTask (that will run on a different thread), then
- update the UI with the results, then
- hide the progress bar.
For example, something like this will work smoothly.
Here is how it works. (The AsyncTask takes 7 seconds)
The UI thread is freed by executing the long running process in the AsyncTask.
This approach is correct from the functional prospect, but it is wrong from the design one, because in the same place we are executing the core business logic and managing the UI components. The MVC design pattern and the EventBus library help us in splitting these concerns.
First of all, we need to add that library to the dependencies of our application.
Then we need to create the model for our data. An instance of this model will be passed by the background task.
Now we define the Runnable that will be executed in a separate thread.
The key point here is that we are using EventBus.getDefault().post(eventModel) to trigger an event. Note how this runnable is independent so reusable.
Now we need to change our activity to run LongRunnable in a new thread and register the event listener.
First of all, we changed the OnClickListener to start the LongRunnable in a new thread.
The @Subscribe annotation tells to the event bus to call this method when an EventModel is posted. The threadMode = ThreadMode.MAIN tells to run it on the UI thread.
The EventBus.getDefault().register(this) and EventBus.getDefault().unregister(this) are used to register and unregister the listener. This is to avoid the event bus searching for dismissed and destroyed activities.
In this way we are using the MVC pattern by splitting, in three different and completely decoupled classes,
- the model (EventModel),
- the view (Main Activity) and
- the controller (LongRunnable).