Related recommendations:

  • The Android source code to read | Handler
  • The Android source code to read | stars
  • The Android source code to read | MessageQueue
  • The Android source code to read | Message
  • Android custom View | distortion effect

Class notes

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 {@link #prepare} in the thread that is to run the loop, and then {@link #loop} to have it process messages until the loop is stopped. <p>Most interaction with a message loop is  through the {@link Handler} class.Copy the code
  • The Looper class typically provides a message loop for the thread.
  • The thread does not have a message loop by default. To create it, call looper. prepare inside the thread and then call looper. loop to process the message until the loop stops.
  • Most of the interaction with the message loop is through the Handler class.
* <p>This is a typical example of the implementation of a Looper thread,
  * using the separation of {@link #prepare} and {@link #loop} to create an
  * initial Handler to communicate with the Looper.
  *
  * <pre>
  *  class LooperThread extends Thread {
  *      public Handler mHandler;
  *
  *      public void run() {
  *          Looper.prepare();
  *
  *          mHandler = new Handler() {
  *              public void handleMessage(Message msg) {
  *                  // process incoming messages here
  *              }
  *          };
  *
  *          Looper.loop();
  *      }
  *  }</pre>
Copy the code

In the class comments, there is an example of using Looper, the core of which is to call two methods: looper.prepare (); And the stars. The loop ();

prepare() & loop()

prepare()

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() ! = null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }Copy the code

In the prepare method, we initialize a ThreadLocal, which is used to hold a thread shared variable: For a static ThreadLocal, different threads can only get, set, and remove their own variables from it without affecting other threads’ variables. That is, the sThreadLocal here will be a different variable in different threads.

The prepare method also limits each thread to one looper.

loop()

public static void loop() { final Looper me = myLooper(); / / to omit... for (;;) { Message msg = queue.next(); // might block // / / 1. MSG. Target, in fact, the handler object, call distribution method try {MSG. Target. DispatchMessage (MSG); } finally { if (traceTag ! = 0) { Trace.traceEnd(traceTag); }} // omit... // 2. After distribution, recycle messageBean msg.recycleunchecked (); }}Copy the code
  • After loop is called, a for loop is entered, which loops indefinitely
  • Message MSG = queue.next(); Blocks the current thread until it gets a message MSG that needs to be processed.
  • After access to the message to be processed, execute MSG. Target. DispatchMessage (MSG); The message is sent to the corresponding handler, and the handler’s handleMessage method is called back to complete the processing of the message
  • Finally, recycle message msg.recycleunchecked ();

A constructor

final MessageQueue mQueue;
final Thread mThread;
private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}
Copy the code

Privatize the constructor, and preserve the current thread reference and initialize a MessageQueue MessageQueue.

prepareMainLooper()

private static Looper sMainLooper;  // guarded by Looper.class

/**
 * Initialize the current thread as a looper, marking it as an
 * application's main looper. The main looper for your application
 * is created by the Android environment, so you should never need
 * to call this function yourself.  See also: {@link #prepare()}
 */
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}
Copy the code

We define a sMainLooper, which is the Looper of the main thread, and the same initialization logic as the Looper of the upper thread.

other

Quit method is to end the queue loop, call the mQueue inside the method, you can see the source code analysis in MessageQueue.

public void quit() {
    mQueue.quit(false);
}
public void quitSafely() {
    mQueue.quit(true);
}
Copy the code

conclusion

  • Looper is the circulator, driving the whole MessageQueue to circulate
  • With ThreadLocal, each word thread has its own unique Looper
  • Looper terminates the queue loop by calling the quit method, which directly discards messages that have not been processed at the appropriate time.

Code word is not easy, convenient if the quality of three even, or pay attention to my public number technology sauce, focus on Android technology, not regularly push fresh articles, if you have a good article to share with you, welcome to pay attention to contribute!