Android -- Looper.prepare() and Looper.loop() -- Deep Edition

Keywords: Android Attribute xml Java

Reprint address: http://blog.csdn.net/heng615975867/article/details/9194219




Android The Looper class in android is a class used to encapsulate message loops and message queues for message processing in android threads. handler can actually be seen as a tool class for inserting messages into message queues.


(1) The Looper class is used to open a message loop for a thread. By default, newborn threads in android do not open message loops. (Except for the main thread, the main thread system automatically creates Looper objects for it and opens the message loop.) Looper objects store messages and events through MessageQueue. A thread can only have one Looper, corresponding to a MessageQueue.  


(2) It usually interacts with Looper through Handler objects. Handler can be seen as an interface of Looper to send messages to a specified Looper and define processing methods. By default, Handler binds to the Loper of the thread in which it was defined, for example, if Handler is defined in the main thread, then it is bound to the Loper of the main thread. mainHandler = new Handler() is equivalent to new Handler (Looper.myLooper(). Looper.myLooper(): Gets the looper object of the current process, and similar Looper.getMainLooper() is used to get the Looper object of the main thread.  


(3) Direct new Handler() in non-main threads will report the following errors: E/Android Runtime (6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception E/Android Runtime (6173): Java.lang.RuntimeException: Can't create handler in thread that has not been called Looper.prepare() because Looper objects are not created by default in non-main threads, so Looper.prepare() needs to be invoked first to enable Looper.  


(4) Looper.loop(); Let Looper start working, cancel messages from message queues, and process messages.  


Note: The code written after Looper.loop() will not be executed. This function should be a loop inside. When mHandler.getLooper().quit() is called, loop will stop and the code will run afterwards.
(5) Based on the above knowledge, the main thread can send messages to sub-threads (non-main threads).  
Declare the mHandler in the following example as a class member and send a message through the mHandler in the main thread. Introduction to Looper in the official Android document: Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class. 

This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.


  1. class LooperThread extends Thread  
  2. {  
  3. public Handler mHandler;  
  4. public void run()   
  5. {  
  6. Looper.prepare();  
  7. mHandler = new Handler()   
  8. {  
  9. public void handleMessage(Message msg)   
  10. {  
  11. // process incoming messages here  
  12. }  
  13. };  
  14. Looper.loop();  
  15. }  

If a message queue is created in a thread using Looper.prepare() and Looper.loop(), message processing can be done in that thread.


Use of android HandlerThread

Handler and looper message queues have been studied before, but handler in android is not executed by another thread, or in the main UI thread, if you want to start another thread, you need to use Handler Thread to implement. When using HandlerThread, you need to implement the CallBack interface to override the handlerMessage method and process your own logic in the handlerMessage method. Here is a small example of the program.

The layout file is simple, just a button to start the HanlderTread thread

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="@string/hello" />  
  11.   
  12.     <Button  
  13.         android:id="@+id/handlerThreadBtn"  
  14.         android:layout_width="wrap_content"  
  15.         android:layout_height="wrap_content"  
  16.         android:text="startHandlerThread" />  
  17.   
  18. </LinearLayout>  

The Activity code is as follows:

  1. package com.tayue;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6. import android.os.Handler.Callback;  
  7. import android.os.HandlerThread;  
  8. import android.os.Message;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12. /** 
  13.  *  
  14.  * @author xionglei 
  15.  * 
  16.  */  
  17. public class TestHandlerActivity extends Activity implements OnClickListener{  
  18.       
  19.     public Button handlerThreadBTN;   
  20.     MyHandlerThread handlerThread;  
  21.     Handler handler;  
  22.       
  23.     /** Called when the activity is first created. */  
  24.     @Override  
  25.     public void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         //Print the name of the UI thread  
  28.         System.out.println("onCreate  CurrentThread = " + Thread.currentThread().getName());  
  29.           
  30.         setContentView(R.layout.main);  
  31.           
  32.         handlerThreadBTN = (Button) findViewById(R.id.handlerThreadBtn);  
  33.         handlerThreadBTN.setOnClickListener(this);  
  34.           
  35.         handlerThread = new MyHandlerThread("myHanler");  
  36.         handlerThread.start();  
  37.         //Note: This constructor of handler must be used here, because callback needs to be passed in so that handler Message of Handler Thread can replace handler Thread which is native to Handler.  
  38.         handler = new Handler(handlerThread.getLooper(), handlerThread);         
  39.     }  
  40.   
  41.     @Override  
  42.     public void onClick(View v) {  
  43.         //Click on the button and then open the thread  
  44.         handler.sendEmptyMessage(1);  
  45.     }      
  46.       
  47.     private class MyHandlerThread extends HandlerThread implements Callback {  
  48.   
  49.         public MyHandlerThread(String name) {  
  50.             super(name);  
  51.         }  
  52.   
  53.         @Override  
  54.         public boolean handleMessage(Message msg) {  
  55.             //Print the name of the thread  
  56.             System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getName());  
  57.             return true;  
  58.         }              
  59.     }           
  60. }  

Click the button and print the following log (click here three times) 07-0609:32:48.776: I/System.out (780): onCreate Current Thread = main 07-0609:32:55.076: I/System.out (780): handleMessage Current Thread = myHanler 07-06:09:32:58.669: I/System.out (780): handleMessage Current Thread = myHanler 07-06.03:476: I/System.out(780):  handleMessage CurrentThread = myHanler

Handler Thread is that simple.

Of course, android itself has an asynchronous thread handler, AsyncTask, which encapsulates Handler Thread and handler to implement asynchronous multithreading operations.

It can also be used as follows:

  1. private boolean iscancel = false//Users manually cancel logon flags  
  2.   
  3.     handlerThread = new HandlerThread("myHandlerThread");  
  4.                     handlerThread.start();  
  5.                     handler = new MyHandler(handlerThread.getLooper());  
  6.                 //Adding the thread object to be executed to the thread queue  
  7.                         handler.post(new Runnable() {  
  8.                             @Override  
  9.                             public void run() {  
  10.                                 Message message = handler.obtainMessage();  
  11.                                 UserBean user = Bbs.getInstance().Login(username, password);//Time-consuming task  
  12.                                 Bundle b = new Bundle();  
  13.                                 b.putSerializable("user", user);  
  14.                                 message.setData(b);  
  15.                                 message.sendToTarget(); //Or use handler.sendMessage(message);  
  16.                             }  
  17.                         });  
  18.     class MyHandler extends Handler {  
  19.   
  20.             public MyHandler(Looper looper) {  
  21.                 super(looper);  
  22.             }  
  23.   
  24.             @Override  
  25.             public void handleMessage(Message msg) {  
  26.                 if(iscancel == false){  
  27.                     //Code to manipulate UI threads  
  28.                     Bundle b = msg.getData();  
  29.                     UserBean user = (UserBean)b.get("user");  
  30.                                      ......  
  31.                }  
  32.            }  
  33.     }    


Android Medium Looper Class, a class used to encapsulate message loops and message queues, is used in android Processing messages in threads. handler Actually, it can be seen as a tool class for inserting messages into message queues.


    (1) Looper Class is used to open a message loop for a thread.     By default android Newborn threads do not open the message cycle. (Except for the main thread, the main thread system automatically creates it Looper Object, open the message loop.)     Looper Object passing MessageQueue To store messages and events. A thread can only have one Looper,Corresponding to one MessageQueue.  


(2) Usually through Handler Object to and Looper Interactive. Handler It can be seen as Looper An interface to a specified Looper Send messages and define processing methods.     By default Handler It will be on the thread where it was defined Looper Binding, for example, Handler Defined in the main thread, then it is with the main thread Looper Binding. mainHandler = new Handler() Equivalent to new Handler(Looper.myLooper()). Looper.myLooper(): Getting the current process looper Objects, similar Looper.getMainLooper() Used to get the main thread Looper Object. 


(3) Direct in non-main threads new Handler() The following errors will be reported: E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception E/AndroidRuntime( 6173): Java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() The reason is that the non-main thread is not created by default. Looper Object, which needs to be called first Looper.prepare()Enable Looper.  


(4) Looper.loop(); Give Way Looper Start work, cancel messages from message queues, and process messages. 


    Note: Write in Looper.loop()Later code will not be executed. This function should be a loop inside when called. mHandler.getLooper().quit()Later, loop It stops, and then the code runs.
(5) Based on the above knowledge, the main thread can send messages to sub-threads (non-main threads). 
    In the following example mHandler Declare as a class member and pass through the main thread mHandler Send a message.         Android Official Documents Looper Introduction: Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class. 

This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.


  1. class LooperThread extends Thread  
  2. {  
  3. public Handler mHandler;  
  4. public void run()   
  5. {  
  6. Looper.prepare();  
  7. mHandler = new Handler()   
  8. {  
  9. public void handleMessage(Message msg)   
  10. {  
  11. // process incoming messages here  
  12. }  
  13. };  
  14. Looper.loop();  
  15. }  

If a message queue is created in a thread using Looper.prepare() and Looper.loop(), message processing can be done in that thread.


Use of android HandlerThread

Handler and looper message queues have been studied before, but handler in android is not executed by another thread, or in the main UI thread, if you want to start another thread, you need to use Handler Thread to implement. When using HandlerThread, you need to implement the CallBack interface to override the handlerMessage method and process your own logic in the handlerMessage method. Here is a small example of the program.

The layout file is simple, just a button to start the HanlderTread thread

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:text="@string/hello" />  
  11.   
  12.     <Button  
  13.         android:id="@+id/handlerThreadBtn"  
  14.         android:layout_width="wrap_content"  
  15.         android:layout_height="wrap_content"  
  16.         android:text="startHandlerThread" />  
  17.   
  18. </LinearLayout>  

The Activity code is as follows:

  1. package com.tayue;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.os.Handler;  
  6. import android.os.Handler.Callback;  
  7. import android.os.HandlerThread;  
  8. import android.os.Message;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12. /** 
  13.  *  
  14.  * @author xionglei 
  15.  * 
  16.  */  
  17. public class TestHandlerActivity extends Activity implements OnClickListener{  
  18.       
  19.     public Button handlerThreadBTN;   
  20.     MyHandlerThread handlerThread;  
  21.     Handler handler;  
  22.       
  23.     /** Called when the activity is first created. */  
  24.     @Override  
  25.     public void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         //Print the name of the UI thread  
  28.         System.out.println("onCreate  CurrentThread = " + Thread.currentThread().getName());  
  29.           
  30.         setContentView(R.layout.main);  
  31.           
  32.         handlerThreadBTN = (Button) findViewById(R.id.handlerThreadBtn);  
  33.         handlerThreadBTN.setOnClickListener(this);  
  34.           
  35.         handlerThread = new MyHandlerThread("myHanler");  
  36.         handlerThread.start();  
  37.         //Note: This constructor of handler must be used here, because callback needs to be passed in so that handler Message of Handler Thread can replace handler Thread which is native to Handler.  
  38.         handler = new Handler(handlerThread.getLooper(), handlerThread);         
  39.     }  
  40.   
  41.     @Override  
  42.     public void onClick(View v) {  
  43.         //Click on the button and then open the thread  
  44.         handler.sendEmptyMessage(1);  
  45.     }      
  46.       
  47.     private class MyHandlerThread extends HandlerThread implements Callback {  
  48.   
  49.         public MyHandlerThread(String name) {  
  50.             super(name);  
  51.         }  
  52.   
  53.         @Override  
  54.         public boolean handleMessage(Message msg) {  
  55.             //Print the name of the thread  
  56.             System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getName());  
  57.             return true;  
  58.         }              
  59.     }           
  60. }  

Click the button and print the following log (click here three times) 07-0609:32:48.776: I/System.out (780): onCreate Current Thread = main 07-0609:32:55.076: I/System.out (780): handleMessage Current Thread = myHanler 07-06:09:32:58.669: I/System.out (780): handleMessage Current Thread = myHanler 07-06.03:476: I/System.out(780):  handleMessage CurrentThread = myHanler

Handler Thread is that simple.

Of course, android itself has an asynchronous thread handler, AsyncTask, which encapsulates Handler Thread and handler to implement asynchronous multithreading operations.

It can also be used as follows:

[java] view plain copy
  1. private boolean iscancel = false; // User manually cancels the logon flag bit
  2.   
  3.     handlerThread = new HandlerThread("myHandlerThread");  
  4.                     handlerThread.start();  
  5.                     handler = new MyHandler(handlerThread.getLooper());  
  6. Adding Thread objects to the thread queue
  7.                         handler.post(new Runnable() {  
  8.                             @Override  
  9.                             public void run() {  
  10.                                 Message message = handler.obtainMessage();  
  11. UserBean user = Bbs.getInstance().Login(username, password); //Time-consuming tasks)
  12.                                 Bundle b = new Bundle();  
  13.                                 b.putSerializable("user", user);  
  14.                                 message.setData(b);  
  15. message.sendToTarget(); //or use handler.sendMessage(message);.
  16.                             }  
  17.                         });  
  18.     class MyHandler extends Handler {  
  19.   
  20.             public MyHandler(Looper looper) {  
  21.                 super(looper);  
  22.             }  
  23.   
  24.             @Override  
  25.             public void handleMessage(Message msg) {  
  26.                 if(iscancel == false){  
  27. Code for operating UI threads
  28.                     Bundle b = msg.getData();  
  29.                     UserBean user = (UserBean)b.get("user");  
  30.                                      ......  
  31.                }  
  32.            }  
  33.     }    

Posted by taiger on Mon, 07 Jan 2019 14:18:12 -0800