Android message mechanism and memory leak of handler

Handler

Every beginner of Android development can't get around the "barrier" of handler. Why is it a barrier? First, this is one of the essence of Android architecture. Second, most people know it but don't know why. See handler today After the post method, I decided to go through the source code and sort out the implementation mechanism of the handler.

Asynchronous update UI

First, let's recite the formula "the main thread does not do time-consuming operations, and the sub thread does not update the UI". This rule should be known for beginners. How can we solve the problems in the formula? At this time, the handler appears in front of us (asynctask is OK, but it is essentially the encapsulation of the handler). Let's have a piece of classic common code (the memory leak problem is ignored here, and we'll talk about it later):

First, create a new handler in the activity:

Then send a message in the child thread:

So far, after the time-consuming operation of the sub thread is completed, the UI is updated asynchronously in the main thread, but the title post is not used. Let's look at the version of post:

On the surface, passing a runnable to the post method is like opening a sub thread, but the UI cannot be updated in the sub thread. Then the problem comes. What's the situation? With this doubt, turn to the source code of handler:

Let's take a look at what an ordinary sendemptymessage looks like:

Encapsulate the parameters we imported into a message, then call sendMessageDelayed:

Call sendmessageattime again:

OK, let's look at post ():

The method has only one sentence. The internal implementation is the same as that of ordinary SendMessage, but there is only one difference: getpostmessage (R):

In this method, we found that the parameters we passed in were encapsulated into a message, but this time it was m.callback = R, just MSG What = what. I don't want to see these properties of message

Android message mechanism

Seeing this, we just know that the principles of post and SendMessage are encapsulated into message, but we still don't know what the whole mechanism of handler looks like. Continue to explore.

Just now I saw that both methods eventually called sendmessageattime

This method calls enqueuemessage again. The name should mean adding messages to the queue. Click to see:

Masynchronous, which is related to asynchrony, let's continue to pass the parameters to the enqueuemessage method of the queue. We'll look at the assignment of the target of the MSG later. Now continue to enter the enqueuemessage method of the messagequeue class. The method is long. Let's look at the key lines:

Sure enough, as the method name says, an infinite loop adds a message to the message queue (in the form of a linked list), but you can take it whenever you put it. How can you get it out of this message?

Looking at the messagequeue method, we found next (). The code is too long to be repeated. We know it is used to get messages. However, where is this method called? Not in the handler. We found the key figure looper. I call him ring Messenger, which is responsible for getting messages from the message queue. The key code is as follows:

Simple and clear, we saw the MSG we just said Target, MSG. Was assigned in the handler just now Target = this, so let's look at the dispatchmessage in the handler:

1. MSG's callback is not empty. Call the handlecallback method (message. Callback. Run()) 2 Mcallback is not empty, call mcallback handleMessage(msg) 3. Finally, if everything else is empty, execute the handler's own handlemessage (MSG) method. The callback of MSG should have thought of something, that is, we use the handler Post (runnable R) the run method of runnable passed in. Here we will mention the Java foundation. Directly calling the run method of the thread is equivalent to calling the method in an ordinary class or executing in the current thread, and no new thread will be opened.

So here, we have solved the initial question, why is a runnable passed in the post or the UI can be updated in the main thread.

Keep looking if MSG The mcallback when the callback is empty depends on the construction method:

There are only the last two specific implementations. You already know how mcallback comes from. Just pass it in the constructor.

Finally, if both callbacks are empty, the handler's own handlemessage (MSG) method is executed, that is, the handlemessage method overridden by the new handler, which is well known.

Looper

I see that there is a doubt here, that is, when we create a new handler, we do not pass in any parameters, and there is no display of calling looper related methods. Where is the creation of looper and method call? In fact, Android itself has helped us with these things. We can find them in the main method of activitythread at the program entry:

summary

We have roughly combed the message mechanism of the handler and the difference between the post method and our commonly used SendMessage method. To summarize, it mainly involves four classes: handler, message, messagequeue and looper:

Create a new handler and send a message through SendMessage or post. The handler calls sendmessageattime to give the message to messagequeue

MessageQueue. The enqueuemessage method puts the message into the queue in the form of a linked list

Loop's loop method calls messagequeue Next () fetches the message and calls the dispatcher's dispatchmessage to process the message

In the dispatchmessage, judge MSG Callback, mcallback, that is, the callback of the post method or constructor will be executed if it is not empty. If it is empty, the handlemessage that we most commonly override will be executed.

Finally, let's talk about the memory leak of the handler, and then take a look at the code of our new handler:

When using inner classes (including anonymous classes) to create a handler, the handler object implicitly holds a reference to the activity.

The handler usually appears with a time-consuming background thread, which sends a message to update the UI after the task is executed. However, if the user closes the activity during the network request, the activity may not be used under normal circumstances, and it may be recycled during GC check. However, since the thread has not finished executing at this time, and the thread holds the reference of the handler (otherwise, how can it send messages to the handler?), This handler also holds a reference to an activity, so that the activity cannot be recycled (i.e. memory leakage) until the end of the network request.

In addition, if the handler's postdelayed () method is executed, there will be a chain of messagequeue - > message - > handler - > activity before the set delay arrives, resulting in your activity being referenced and unable to be recycled.

One solution is to use weak references:

The above is the data sorting of Android handler message mechanism. We will continue to supplement relevant data in the future. Thank you for your support to this site!

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>