SoFunction
Updated on 2025-03-11

Android inter-thread communication Detailed explanation of Handler usage

Preface

Handler is one of the overlords in the interview questions. In my "Interview Memoir", there is almost no company that doesn't ask this question during the interview. To be simple, ask about usage process, memory leaks and other issues. To be more complicated, please correct the source code details and the underlying epoll mechanism to dispose of you. So its importance is self-evident.

So today let’s unveil the mystery of Handler. In order for readers to read easily and not to burn their brains, this series of articles followsUser, source code, interviewLet’s analyze it in a brief article.

01. Definition

Before we understand how to use it, let’s take a look at what is Handler?

A Handler allows you to send and process and Runnable objects associated with a thread's .

The thread-related Runnable object can be sent and processed using the Handler.

This may sound a little confusing. Let’s talk about a common scenario to lead to Handler. You have received a request: there is a file list. After clicking on the file, you will start downloading the file. After the download is completed, add the downloaded logo to the corresponding file in the list.

Downloading is a time-consuming action. In order not to cause ANR (Application not response), we usually need to complete this task through child threads. But under normal circumstances (in special cases), we cannot update the UI in non-main threads, so we need to communicate between threads. And Handler plays its role - conducting inter-thread communication.

02. Use

Step 1: Create

When creating a Handler, you need to pay attention to whether it is in the main thread or the child thread.

//Main threadprivate val mHandler: Handler = object : Handler(()) {
    override fun handleMessage(msg: Message) {
        when () {
            1 -> {}
        }
    }
}
//SubthreadThread {
    ()
    val handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            when () {
                1 -> {}
            }
        }
    }
    (1)
    ()
}.start()

We do not need to call the creation in the main thread()and()

Two methods are required to manually call in the child thread. As for why these two methods are mainly the main line, in the application portalmain()The Chinese system has completed it for us, please see the following principles for details.

Step 2: Send a message

There are two major ways to send messages (timed and delayed sending are ignored here)

The first one is post(Runnable)

// The writing method is not simplified, for better understanding(object :Runnable{
    override fun run() {
        // TODO specific business logic    }
})

The second type is sendMessage(Message)

val msg = Message()
 = 1
 = "Quincy"
(msg)

But in fact, there is no difference between the two in essence. Because both of the above methods were called in the endsendMessageDelayed(), but the source code helps us wrap Runnable into a Message. See the next article for details, source code.

Step 3: Processing messages

Processing messages is not simplyhandleMessage()It only needs to be processed in the middle, it still depends on the situation. For the sake of easy analysis, let's take a brief look at the source code of the message processing

public void dispatchMessage(Message msg) {
    if ( != null) {
        handleCallback(msg); // Comment 1    } else {
        if (mCallback != null) { 
            if ((msg)) {
                return; //Note 2            }
        }
        handleMessage(msg); //Note 3    }
}

Pay attention to the above three notes and their relationship. ifNot empty, that is,post()If the message is sent, it will be calledhandleCallback(Message)

private static void handleCallback(Message message) {
        ();
    }

Otherwise, if mCallback is not empty and the message is intercepted, it will no longer be calledhandleMessage()

private val handler = object : Handler(object : Callback {
    override fun handleMessage(msg: Message): Boolean {
        if ( == 1) {
            return true//Not calling comment 3        }
        return false//Comment 3 will be called    }
}) {
    override fun handleMessage(msg: Message) {
        when () {
            1 -> {}
        }
    }
}

Otherwise, the callback will be made.

private val mHandler: Handler = object : Handler() {
    override fun handleMessage(msg: Message) {
        when () {
            1 -> {}
        }
    }
}

03. Conclusion

The above is the use of Handler, which mainly shares the basic usage methods and uses them as the basis for the source code. Finally, I would like to ask a few questions. You can take the questions to see the source code. In the next article, we will uncover the answer.

  • There are multiple Handlers in a thread, but there is only 1 Looper and 1 MessageQueue. Where to distribute messages, how do you know which Handler to send?
  • How many are there in Loopersfor( ; ; ), What is the function of the difference?
  • After the message is processed, how is the Message processed?
  • Why does Handler cause memory leaks?
  • There is a Looper's vicious cycle in Handler, why is it not stuck? (I think it's just to get stuck "dead", and it's because of it that our program does not exit)

The above is the detailed explanation of the use of Android thread communication Handler. For more information about Android thread communication Handler, please follow my other related articles!