Android Handler Example

Android is a message-driven system, it implements the message loop mechanism through Looper and Handler. The message loop of Android is thread-oriented, each thread can have its own message queue and message loop.

The Looper in the Android system manages the message queue and message loop of the thread. Looper.myLooper() method can return current thread’s Looper object, and Looper.getMainLooper() method will return current process’s main thread’s Looper object.

android-handler-looper-architecture-diagram

1. Android Child Thread Example.

  1. Now let us look at the below example first. The below example does not use Handler. When the button is clicked, a message should be displayed under it.
    android-handler-example
  2. activity_handler.xml
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        tools:layout_editor_absoluteY="8dp"
        tools:layout_editor_absoluteX="8dp">
    
        <Button
            android:id="@+id/handlerExampleButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Click Me" />
    
        <TextView
            android:id="@+id/handlerExampleTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="" />
    </LinearLayout>
  3. HandlerActivity.java
    package com.dev2qa.example;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class HandlerActivity extends AppCompatActivity {
    
        private Button handlerExampleButton;
    
        private TextView handlerExampleTextView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_handler);
    
            setTitle("dev2qa.com - Handler Example");
    
            // Get the button.
            handlerExampleButton = (Button)findViewById(R.id.handlerExampleButton);
            handlerExampleButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // Start a child thread when button is clicked.
                    WorkerThread workerThread = new WorkerThread();
                    workerThread.start();
                }
            });
    
            // Get the TextView which show button click message.
            handlerExampleTextView = (TextView)findViewById(R.id.handlerExampleTextView);
        }
    
        // This is a child thread class.
        private class WorkerThread extends Thread{
            @Override
            public void run() {
                // This line code will throw an exception, because can not update UI component status in child thread.
                handlerExampleTextView.setText("Above button has been clicked.");
            }
        }
    }
  4. But when you run it, you may encounter the below exception.
    com.dev2qa.example E/AndroidRuntime: FATAL EXCEPTION: Thread-4
                                         Process: com.dev2qa.example, PID: 7878
                                         android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can tou
                                             at android.view.ViewRootImp1.checkThread(ViewRootImpl.java: 6391)
                                             ......
                                             at com.dev2qa.example.HandlerActivity$WorkerThread.run(HandlerActivity.java:38)
    
  5. This is because of the following reasons.
  6. Android UI components are not thread-safe.
  7. Can not update android view components in child thread.
  8. Only the application main thread can modify view components.

2. Use Android Handler To Communicate Between Child Thread And Main Thread.

  1. To resolve the above error, we should use android.os.Handler and android.os.Message class.
  2. We should create the message object in the child thread and then use the main thread Handler object to put the message in the main thread message queue, below is the example source code.
    package com.dev2qa.example;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class HandlerActivity extends AppCompatActivity {
    
        private Button handlerExampleButton;
    
        private TextView handlerExampleTextView;
    
        private Handler mainThreadHandler;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_handler);
    
            setTitle("dev2qa.com - Handler Example");
    
            // This handler is used to handle child thread message from main thread message queue.
            mainThreadHandler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    if(msg.what == 1)
                    {
                        // Update view component text, this is allowed.
                        handlerExampleTextView.setText("Above button has been clicked.");
                    }
                }
            };
    
            // Get the button.
            handlerExampleButton = (Button)findViewById(R.id.handlerExampleButton);
            handlerExampleButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // Start a child thread when button is clicked.
                    WorkerThread workerThread = new WorkerThread();
                    workerThread.start();
                }
            });
    
            // Get the TextView which show button click message.
            handlerExampleTextView = (TextView)findViewById(R.id.handlerExampleTextView);
        }
    
        // This is a child thread class.
        private class WorkerThread extends Thread{
            @Override
            public void run() {
                // Create a message in child thread.
                Message childThreadMessage = new Message();
                childThreadMessage.what = 1;
                // Put the message in main thread message queue.
                mainThreadHandler.sendMessage(childThreadMessage);
            }
        }
    }
  3. Now the app will not throw exceptions when you click the button. And you can see the message text under the button also, below is the demo video on youtube, if you can not watch the above video, you can see it on the youtube URL https://youtu.be/n5vW6xUcqDQ

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.