“This is the 16th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

In the previous article we introduced child threads that send messages to the main thread.

The main thread sends messages to child threads

new Thread(new Runnable(){
    @Override
    public void run(a) {
        Looper.prepare();
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                // Process the message
                switch (msg.what) {
                    case 1:
                        Log.d(TAG, "Received message:"+msg.obj);
                        break;
                    default:
                        break; }}}; Looper.loop(); } }).start(); Button button=findViewById(R.id.bt); button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Message msg = Message.obtain();
        msg.what = 1;
        msg.obj = "Message from master thread";
        // Send messages to child threadshandler.sendMessage(msg); }});Copy the code

The main difference is that looper.prepare () is called before the Handler is created in the child thread and looper.loop () is called after it. But why don’t you do that in the main thread? In the system main thread the system is already created.

public static void main(String[] args) {
    / /...
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
​
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
​
    if (false) {
        Looper.myLooper().setMessageLogging(new
                                            LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Looper.loop();
}
Copy the code

The Looper created in the main thread is in the ActivityThread.main method, which is the entry point to the App.

  1. PrepareMainLooper (), which is actually called Looper. Loop, initialize Looper, MessageQueue, etc.
  2. The member variable Handler mH is initialized when the ActivityThread is created.
  3. Assign the member variable mH to sMainThreadHandler
  4. Finally, looper.loop () is called to start an endless loop, and messages are extracted from MessageQueue for processing.

This is how Looper is created in the main thread.

Principles of Handler mechanism

The Handler mechanism is mainly designed in four parts: Message, Hanlde, Looper, and Message queue.

1.Looper

First, understand its construction method.

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

The MessageQueue object is initialized when Looper is created. The most important methods are prepare() and loop(), which are analyzed respectively in the following sections.

prepare()

Prepare ()->prepare(true)

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

ThreadLocal is an internal data store class that stores data in a specified thread. Once the data is stored, only the specified thread can retrieve the stored data. Other threads cannot retrieve the data. This ensures that each thread has one Looper, and the source code also shows that a thread can only have one Looper, otherwise an exception will be thrown.

loop()

More on that later.