Handler in Android


Main Thread

Android handles all the UI operations and input events from one single thread which is known as called the Main or UI thread. Android collects all events in this thread in a queue and processes this queue with an instance of the Looper class.

Android supports Thread class to perform asynchronous processing. Android also supplies java.util.concurrent package to perform background task like using the ThreadPools and Executor classes.


Why Handler

If you need to update the UI from another main Thread, you need to synchronize with the main thread. Because of this restrictions and complexity, Android provides additional constructed classes to handle concurrently in comparison with standard Java i.e. Handler or AsyncTask.

A Handler allows communicating back with UI thread from other background thread. This is useful in android as android doesn’t allow other threads to communicate directly with UI thread.


How Handler works




A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue.

When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

There are two main uses for a Handler:
(1)  To schedule messages and runnables to be executed as some point in the future. In other words perform action on same thread in future.
(2)  To enqueue an action to be performed on a different thread than your own. In other words enqueue an action to perform on different thread.


How to schedule

Scheduling messages is accomplished with the post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long) methods.

The post versions allow you to enqueue Runnable objects to be called by the message queue when they are received.

The sendMessage versions allow you to enqueue a Message object containing a bundle of data that will be processed by the Handler's handleMessage(Message) method (requiring that you implement a subclass of Handler).


Difference between post() and sendMessage()

Conventionally you use post() when you want to execute some code on the UI Thread without having to know anything about your Handler object. It makes sense in many cases where arbitrary code needs to be executed on the UI Thread.
But in some cases you want to organize what is being sent to the UI Thread and have specific functions you want to execute that way you can use sendMessage().


Example

Below are the code snipped explains use of Handler’s post() method-

Android Activity Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:gravity="center"
   
android:orientation="vertical">

    <
TextView
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:layout_gravity="center"
       
android:text="@string/click_start_button" />

    <
ProgressBar
       
android:id="@+id/progressBar"
       
style="?android:attr/progressBarStyleHorizontal"
       
android:layout_width="match_parent"
       
android:layout_height="wrap_content"
       
android:layout_margin="10dp"
       
android:indeterminate="false"
       
android:max="10" />

    <
Button
       
android:id="@+id/buttonStart"
       
android:layout_width="wrap_content"
       
android:layout_height="wrap_content"
       
android:text="@string/start" />
</
LinearLayout>

Android Activity (MainActivity.java)


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;


public class MainActivity extends Activity implements View.OnClickListener {

    private Handler mHandler;
    private ProgressBar mProgressBar;
    private Button mStartButton;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler = new Handler();
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mStartButton = (Button) findViewById(R.id.buttonStart);
        mStartButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.buttonStart:
                startProgress();
                break;
        }
    }

    private void startProgress() {
//      New thread to perform background operation
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <= 30; i++) {
                    final int currentProgressCount = i;
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

//                  Update the value background thread to UI thread
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mProgressBar.setProgress(currentProgressCount);
                        }
                    });
                }
            }
        }).start();
    }
}

For the curious, you can check out the code on Github.

For more detail on Handler please refer -


To find more interesting topics on Software development follow me at https://medium.com/@ankit.sinhal

You can also find my Android Applications on play store




Comments

Popular posts from this blog

Android Performance: Avoid using ENUM on Android

Smart way to update RecyclerView using DiffUtil

Android O: Impact On Running Apps And Developer Viewpoint