Handler

![](http://upload-images.jianshu.io/upload_images/1427878-1c8c9252d8d2f8ac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

>Foreword: Handler mechanism should be the most explained online One of the mechanisms (there is no one), this article introduces the Handler mechanism in an easy-to-understand language, so that everyone can understand it better.

##What is the Handler mechanism?
The Handler mechanism is a very important mechanism for processing asynchronous messages provided by the Android SDK. It is mainly composed of Handler, Looper, Message and MessageQueue. Handler is only a part of the message processing mechanism.
- Message: Message (divided into hardware-generated messages and software-generated messages).
- MessageQueue: message queue, mainly to deliver messages to the message pool (MessageQueue.enqueueMessage) and take away the messages in the message pool (MessageQueue.next).
- Handler: The main function is to send messages to the message pool (Handler.sendMessage) and process messages (Handler.handleMessage).
- Looper: Non-stop loop execution (Looper.loop), take out the Message from the MessageQueue and send it to the Handler.
######Analyze the above parts:
**Message**: What are hardware messages and software messages? The hardware message is that we slide, touch and click the button, etc., and the software message is that we actively send out the new Message. Message implements the Parcelable interface to encapsulate message data, so it exists in memory. An entity (class) must implement this interface if it needs to be encapsulated into a message.
**MessageQueue**: Equivalent to a container, a message pool. As seen above, .next should be guessed that it is in the form of a linked list. In fact, it is indeed a singly linked list maintenance, which has advantages in insertion and deletion. In its next(), there will be an infinite loop, constantly judging whether there is a message, and returning this message and removing it.
**Looper**: Looper will create a MessageQueue when it is created, and the two of them are in a one-to-one correspondence. When Looper.loop() is called, the message loop starts, and the next() method of MessageQueue is called continuously. When there is a message, it will be processed, otherwise it will be blocked in the next() method. loop() is an infinite loop like next() of MessageQueue (see for(;;) in the source code). Call Looper.quit() when exiting, it will call the quit() method of MessageQueue, next will return null, and then the loop() method will also exit.
**Handler**: The Handler is constructed in the main thread, and the method Looper.myLooper() is called in new Handler(). This method is to get the Looper of the current thread. When other threads call sendMessage(), the MessageQueue of the main thread will insert a Message, which is then used by Looper, and sent to Handler by callback msg.target.dispatchMessage(msg); in Looper's loop(). The relationship between Handler and Looper is many-to-one.

A snippet of Looper's source code: ![](http://upload-images.jianshu.io/upload_images/1427878-726ae596b9e7337f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

**Explain The division of labor of each part summarizes the relationship between them: **Handler is responsible for sending messages (Message) to MessageQueue, and Looper is responsible for cyclically receiving messages in MessageQueue and returning them to Handler itself through the callback method.
![Handler mechanism flow chart](http://upload-images.jianshu.io/upload_images/1427878-6df2837aaa26b267.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

##Easy to ignore Message , What should be paid attention to when using it?
Message seems to be very inconspicuous in the Handler mechanism, but it is very important. It encapsulates the information carried by the task and the handler of the task. When using it, you should pay attention to:
- Message can be obtained through new, but usually use the Message.obtain() or Handler.obtainMessage() method to obtain an empty message object from the message pool , you can save resources!
- If Message only needs to carry simple int data, arg1 and arg2 are preferred to pass data, which saves memory than Bundle.
- Use Message.what to identify information for easy processing of Message.
- Finally, if you need to return a lot of data information from the worker thread, then use the Bundle object to put the data together in the obj property, and return to the main thread for processing.

##Looper source code brief:

I have mentioned so many methods of Looper above, but I have not seen the shadow of Looper when using Handler in Activity. It turns out that Activity contains a Looper object, which will automatically manage Looper and process child threads message sent from . As mentioned earlier, when the Handler is initialized, the Looper of the current thread is associated with the Handler in the constructor of the Handler, so there is no need to explicitly use the Looper in the Activity. ![](http://upload-images.jianshu.io/upload_images/1427878-e66bbdb02d965cae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) But in the child thread, we need to maintain it ourselves Looper. ![](http://upload-images.jianshu.io/upload_images/1427878-97b65b41172b9090.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)![](http://upload- images.jianshu.io/upload_images/1427878-294e70017b409686.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#####Source code brief
The most detailed explanation of the online article introducing the Handler mechanism is Looper, which will be explained thoroughly with each source code. Here is a brief summary of Looper. For details, please check the Looper source code. ![](http://upload-images.jianshu.io/upload_images/1427878-a6268d0e2c81e5ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) You can see the core of how Prepare() works That is, define the Looperd object as ThreadLocal, and add the only Looper object to ThreadLocal. ![](http://upload-images.jianshu.io/upload_images/1427878-f143502e3330d143.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) Looper creates a MessageQueue and The current thread Thread.
**So what is TheadLocal? **
ThrealLocal is a generic class.
**Working principle**: When ThreadLocal stores data, it first obtains the current thread, and then creates Values ​​through the current thread. If there is no Values, a new Values ​​instance is created. Then store the passed in Value. When it is obtained, it is also obtained according to the Values ​​of the current thread.
Its get() and set() methods are as follows: ![](http://upload-images.jianshu.io/upload_images/1427878-b130c6fd389ccdb6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w /1240)![](http://upload-images.jianshu.io/upload_images/1427878-c593dd6b450529ef.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)**Scenario**: Data is thread-scoped and can be used when different threads have different copies of the data.

##Finally talk about why the Handler mechanism causes memory leaks
because of non-static inner classes!
We know that the non-static inner class will hold the reference of the outer class by default. When the life cycle of the non-static inner class object is longer than that of the outer class, it will cause memory leaks. ![](http://upload-images.jianshu.io/upload_images/1427878-1e301696884b8fff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
When I introduced Message above, I said that mHandler will be saved as a member variable in the sent message msg, so msg will hold the reference of mHandler, and mHandle is the non-static inner class instance of MainActivity, so mHandler holds the reference of MainActivity. msg indirectly holds a reference to MainActivity. msg is sent to the message queue (MessageQueue) to wait for Looper to poll for processing. When MainActivity exits, msg may still be unprocessed or being processed in the message queue. This will cause MainActivity to be unable to be recycled, resulting in a memory leak of MainActivity.
**Solution: use static inner class + weak reference method**![](http://upload-images.jianshu.io/upload_images/1427878-958141fc061c2d66.png?imageMogr2/auto-orient/strip%7CimageView2/ 2/w/1240) mHandler holds MainActivity by weak reference. When GC executes garbage collection, it will reclaim and release the occupied memory unit when it encounters MainActivity to avoid memory leakage. msg may also exist in MessageQueue, so when MainActivity is destroyed, the callback of mHandler and the message sent are removed. ![](http://upload-images.jianshu.io/upload_images/1427878-9798d9d2daf8728f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

##End
At this point, the content of the Handler mechanism is finished, but this article only introduces the Handler mechanism in a relatively easy-to-understand way. The Handler mechanism can be seen everywhere in Android development. It is also very important. It is necessary for everyone to study it in depth, take a look at the source code inside or combine some articles explaining the source code to understand it by yourself. I hope it can help you, and if there is anything wrong, please point out.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325423522&siteId=291194637