Android HandlerThread summary

preface

I used to be [simple use of Android Handler and Loop] This paper introduces the communication between sub threads and sub threads.

One middle note is that we need to call Looper. in the child thread. Prepare() starts a message loop for a thread. By default, the newly born thread in Android does not start a message loop. (except for the main thread, the main thread system will automatically create a looper object for it and start the message loop.) Message and loopqueue objects are used to store messages. A thread can only have one looper, corresponding to a MessageQueue. Then through looper Loop () makes looper work, fetching messages from the message queue and processing messages.

Note: write in looper The code after loop () will not be executed. There should be a loop inside this function when calling mhandler getLooper(). After quit (), loop will be suspended and the subsequent code can be run.

However, we can use the HandlerThread class to help us do these logical operations.

HandlerThread

HandlerThread is essentially an ordinary Thread, but Looper is built inside

General usage of HandlerThread

  • Create a HandlerThread

mThread = new HandlerThread("handler_thread");

  • Start a HandlerThread

mThread.start();

  • Exit loop
    Loop drives the message loop by calling the loop method: block a message from the MessageQueue, and then let the Handler process the message. The loop method is an endless loop method.

How do you end the message loop? We can call Looper's quit method or quitsafe method, which are slightly different.

 /**
     * Quits the looper.
     * <p>
     * Causes the {@link #loop} method to terminate without processing any
     * more messages in the message queue.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p><p class="note">
     * Using this method may be unsafe because some messages may not be delivered
     * before the looper terminates.  Consider using {@link #quitSafely} instead to ensure
     * that all pending work is completed in an orderly manner.
     * </p>
     *
     * @see #quitSafely
     */
    public void quit() {
        mQueue.quit(false);
    }

    /**
     * Quits the looper safely.
     * <p>
     * Causes the {@link #loop} method to terminate as soon as all remaining messages
     * in the message queue that are already due to be delivered have been handled.
     * However pending delayed messages with due times in the future will not be
     * delivered before the loop terminates.
     * </p><p>
     * Any attempt to post messages to the queue after the looper is asked to quit will fail.
     * For example, the {@link Handler#sendMessage(Message)} method will return false.
     * </p>
     */
    public void quitSafely() {
        mQueue.quit(true);
    }

Similarities:
Add new events that are not accepted to the message queue.

difference
When we call Looper's quit method, we actually execute the removeAllMessagesLocked method in MessageQueue. The function of this method is to empty all messages in the MessageQueue message pool, whether delayed messages (delayed messages refer to messages sent through sendMessageDelayed or postDelayed methods) or non delayed messages.

When we call Looper's quitsafe method, we actually execute the removeAllFutureMessagesLocked method in MessageQueue. From the name, we can see that this method will only empty all delayed messages in the MessageQueue message pool and send all non delayed messages in the message pool to the Handler for processing. The safety of quitsafe compared with quit method is that it will send all non delayed messages before emptying messages.

Whether the quit method or the quitsafe method is called, Looper will not receive new messages. That is, after calling the loop's quit or quitsafe methods, the message cycle ends. At this time, when calling sendMessage or post methods through the Handler to send messages, false is returned, indicating that the message has not been successfully put into the message queue MessageQueue because the message queue has exited.

It should be noted that loop's quit method exists from API Level 1, but loop's quitsafe method is added from API Level 18.

Small example:

package com.app;

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private HandlerThread myHandlerThread ;
    private Handler handler ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Create a thread with the name: handler thread
        myHandlerThread = new HandlerThread( "handler-thread") ;
        //Start a thread
        myHandlerThread.start();
        //Create a handler object in this thread
        handler = new Handler( myHandlerThread.getLooper() ){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                //This method runs in the handler thread thread and can perform time-consuming operations
                Log.d( "handler " , "Message: " + msg.what + "  Thread: " + Thread.currentThread().getName()  ) ;

            }
        };

        //Send message to handler in main thread
        handler.sendEmptyMessage( 1 ) ;

        new Thread(new Runnable() {
            @Override
            public void run() {
             //Send data to handler in sub thread
             handler.sendEmptyMessage( 2 ) ;
            }
        }).start() ;

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        //Release resources
        myHandlerThread.quit() ;
    }
}


Operation effect:

/com.app D/handler: Message: 1 thread: handler-thread
/com.app D/handler: Message: 2 thread: handler-thread

Characteristics of HandlerThread

  • HandlerThread transfers the loop to the sub thread for processing. In other words, it will share the workload of the mainloop, reduce the pressure of the main thread and make the main interface smoother.

  • Start a thread to play the role of multiple threads. The processing task is executed serially and processed in the order of message sending. HandlerThread is essentially a thread. Within the thread, the code is processed serially.

  • However, because each task will be executed one by one in the form of queue, once a task in the queue takes too long, the subsequent tasks will be delayed.

  • HandlerThread has its own message queue, which does not interfere with or block UI threads.

  • For network IO operations, HandlerThread is not suitable because it has only one thread and has to queue one by one.

     

Tags: Android

Posted by hazel999 on Thu, 21 Apr 2022 03:17:39 +0300