How to use Looper and Handler correctly

How to use Looper and Handler correctly

   there are many articles about Looper parsing on the Internet. I believe that all Android developers can't be familiar with the use of Handler. What's the significance of this article? Of course, I won't introduce any Looper Handler Message mechanism. If you don't know the Handler Message mechanism, please Self propelled Baidu.
   to understand the following, you need to be able to use the Handler normally and understand the Looper mechanism. First, let's talk about several important methods of Looper:

{
    Looper.prepare();// Looper initialization. Looper must be initialized using Handler Looper message mechanism
    Looper.myLooper();// Gets the Looper object of the ThreadLocal cache in the current call thread.
    Looper.loop();//The main premise of the Handler mechanism is to make the calling thread enter a dead cycle. Yes, the main thread in Android is always in a dead cycle

    //getLooper() is a method in the Handler. Get the cached Looper object in the Handler. Use the Handler parameterless construction to create the calling thread
    //The Looper object, which uses the Handler(Looper looper) structure to create the Looper object that will cache the incoming;

    mHandler.getLooper().quit();//Terminate the Looper.looper() loop. After executing quit, the Handler mechanism will fail. When executing
    //If there is a Message not executed in MessageQueue, it will not execute the unexecuted Message and exit directly. After calling quit, it will not be able to send a Message to the Handler

    mHandler.getLooper().quitSafely();//Android 4.3, the method added after API level 18 has the same effect as quit(), but it is terminated
    //Looper will execute all non delay tasks in the message queue before calling quit, and cannot send messages to Handler
}

   it's very simple for a child thread to use Looper. If you don't have many words, continue with the code:

    Handler mHandler;
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();//Looper initialization
                //It should be noted that the Handler initialization passed in the Looper object is the cached Looper object in the child thread
                mHandler = new Handler(Looper.myLooper());
                Looper.loop();//Dead cycle
                //Note: the location code after Looper.loop() will not execute until Looper exits, (not forever)
            }
        }).start();

   the above code has initialized the Looper and Handler in the sub thread. Only we can use the Handler in other threads (main or sub thread) to send messages to the current sub thread:

    Handler mHandler;
    int count = 5;
    public void main(String[] args){
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();//Looper initialization
                //It should be noted that the Handler initialization passed in the Looper object is the cached Looper object in the child thread
                mHandler = new Handler(Looper.myLooper());
                Looper.loop();//Dead cycle
                //Note: the location code after Looper.loop() will not execute until Looper exits, (not forever)
            }
        }).start();
        //Main thread notice that the main thread delays sending messages to the sub thread for one second because the creation of the sub thread takes time. If the Handler is not ready to send messages immediately, an exception will be thrown
        Log.log("count: ---> " + " ThreadName: " + Thread.currentThread().getName());
        //MainThread is a class that I customized. A main thread Handler is cached internally
        MainThread.getHandler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //Use the mHandler in the subthread to send a delay message to the subthread
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if(count >= 0) {
                            //Print current thread name
                            Log.log("count: ---> " + count+" ThreadName: "+Thread.currentThread().getName());
                            count--;
                            //Continue sending messages to child threads
                            mHandler .postDelayed(this,1000);
                        }else if(count >= -10){
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                                mHandler.getLooper().quitSafely();
                            }else {
                                mHandler.getLooper().quit();
                            }
                            Log.log("quit: count: ---> " + count+" ThreadName: "+Thread.currentThread().getName());
                            count--;
                            //Continue sending messages to child threads
                            mHandler .postDelayed(this,1000);
                        }
                    }
                },1000);
            }
        },1000);
    }

After execution, the Log is printed as follows: it is obvious that we use the Handler in the sub thread in the right way

It's said that HandlerThread encapsulates the sub thread + Handler. I haven't used it before. Let's talk about it. You can see the source code if you are interested in it

Tags: Android

Posted on Fri, 31 Jan 2020 05:26:18 -0800 by fahad