Handler is a thread that communicates with other threads. We discuss and study together. First, understand that a thread has only one Looper and MessageQueue. The Handler calling this thread can only send messages to the MessageQueue of this thread. So how do you tell which thread this Handler belongs to, by the Looper object in this Handler object. The thread Looper object loop() then keeps fetching messages from MessageQueue.

1. The main thread initializes the Handler

Private Handler Handler = newHandler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ ... }}};Copy the code

I’ll just create a new Handler for the main thread. The answer is in the source code. See below.

//Handler source code fragmentif(FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); . mLooper = Looper.myLooper(); Pay attention to this sentenceif (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()"); }...Copy the code

mLooper = Looper.myLooper(); This code gets the main thread’s Looper, which is already initialized in ActivityThread, so I won’t go into details here.

2. The child thread sends a message to the main thread

A. Send messages in child threads

private void childThreadSendMessageToMain() {
        new Thread(){
            @Override
            public void run() {
                super.run();
                Message message = handler.obtainMessage();
                message.what = mess_thread1;
                message.obj = "This is a message from child thread 1."; handler.sendMessage(message); }}.start(); }Copy the code

handler.sendMessage(message); The handler that we initialized above on the main thread is the handler for the main thread, so that the handleMessage() of the main thread can receive messages from the child thread

B. Receive messages on the main thread

public void handleMessage(Message msg) { super.handleMessage(msg); Switch (msg.what){// notice herecase mess_thread1:
                    Log.d(TAG, "HandleMessage: message received from mess_thread1");
                    Log.d(TAG, "handleMessage: msg.obj="+ msg.obj); . }}Copy the code

C. Print the results

D/ScrollingActivity: handleMessage: Received a message from mess_thread1 D/ScrollingActivity: handleMessage: msg.obj= I am a message from child thread1Copy the code

2. The main thread sends messages to child threads

I have a question here, what happens when I use a child thread Handler on the main thread, and the child thread’s Handler doesn’t initialize properly? Again: the child thread sends a message to the main thread: the child thread’s Handler is ready. Again: the main thread sends a message using the child thread’s Handler. Finally, the child thread receives and processes the message sent by the main thread

A. We change the way we write it and write a class on the main thread that inherits from Handler

Private class ChildHandler extends Handler{// When a child thread is passed a looper, the Handler becomes the child thread's private ChildHandler(looper) looper){ super(looper); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ ... }}}Copy the code

B. Start new Handler in child thread and send message

private void initChildHandler(){
        new Thread(){
            @Override
            public void run() {
                Looper.prepare();
                childThreadHandler = new ChildHandler(Looper.myLooper());
                Message message = handler.obtainMessage();
                message.what = child_handler_ok;
                message.obj = "Child thread handler is ready.";
                handler.sendMessage(message);
                Looper.loop();

            }
        }.start();
    }
Copy the code

C. The main thread receives the message “child handler is ready” and uses the child’s handler to send the message to the child thread

Private Handler Handler = newHandler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case child_handler_ok:
                    Log.d(TAG, "HandleMessage: child thread message received");
                    Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
                    sendMessageToChildThread();
                    break; }}};Copy the code

D.s endMessageToChildThread method of concrete realization

// Use child thread handler to send messages to child thread private voidsendMessageToChildThread() {
        Message message = childThreadHandler.obtainMessage();
        message.what = mess_mainThread;
        message.obj = "I'm the main thread. I've received a message from the child thread handler.";
        childThreadHandler.sendMessage(message);
    }
Copy the code

E. Child threads receive messages from the main thread

private class ChildHandler extends Handler{
        private ChildHandler(Looper looper){
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case mess_mainThread:
                    Log.d(TAG, "handleMessage: mess_mainThread");
                    Log.d(TAG, "handleMessage: msg.obj="+ msg.obj); .break; . }}}Copy the code

F. Print results

HandleMessage: child_handler_OK handleMessage: msg.obj= Child thread Handler is ready handleMessage: mess_mainThread handleMessage: Msg. obj= I am the main thread and have received a message prepared by the child thread handlerCopy the code

3. The child thread sends a message to the child thread

A. Then we create a new thread, called child thread 2. The original child thread is called child thread 1.

// Use the handler of child thread 2 to send messages, which implements communication between child threadsinitChild2Thread() {
        new Thread(){
            @Override
            public void run() {
                Message message = childThreadHandler.obtainMessage();
                message.what = child2_thread;
                message.obj = "I'm a message sent by another child thread.";
                childThreadHandler.sendMessage(message);
            }
        }.start();
    }
Copy the code

B. We receive in child thread 1

This handler extends handler {private class ChildHandler extends Handler{private. This handler extends handler {private ChildHandler(Looper looper){ super(looper); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ ...case child2_thread:
                    Log.d(TAG, "handleMessage: child2_thread" );
                    Log.d(TAG, "handleMessage: msg.obj=" + msg.obj);
                    break; }}}Copy the code

C. Print the results

D/ScrollingActivity: handleMessage: child2_thread D/ScrollingActivity: handleMessage: msg.obj= I am a message sent by another child threadCopy the code

4. To summarize

To send a message to any thread, call sendMessage(message) using the Handler object of the target thread. The difference between which thread the Handler is on is which thread’s Looper the Handler is holding.