Android memory optimization: Handler
Handler is often mentioned in articles to avoid Memory leakage because it is strongly referenced by objects. For example, a Handler object is running in an Activity.
private Handler handler;handler = new Handler(){@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);}};Message message = new Message();message.what = 1;handler.sendMessage(message);When we use the above code to create a Handler, IDE will prompt me
This Handler class shocould be static or leaks might occur (com. example. androidtest. MainActivity.2)
It tells us that memory leakage will occur.
When the Activity is disabled, Handler may not be able to complete the processing, but the Handler may reference the Activity. As a result, GC cannot recycle the Activity object and cause memory leakage. So why is Handler like this? Let's look at its implementation.
The Handler object is implicitly referenced to the Activity, which forms a strong reference and is also the cause of Memory leakage.
Handler is used to process messages, so there must be an object for message distribution, which is logoff.
When the process starts, ActivityThread will create a loop object, loop object research, refer to Lao Luo Article http://blog.csdn.net/luoshengyang/article/details/6817933
Public static void prepareMainLooper () {// call prepare to create Looper prepare (false); synchronized (lochro. class) {if (sMainLooper! = Null) {throw new IllegalStateException (The main Looper has already been prepared .);} smainloid = myLooper () ;}} private static void prepare (boolean quitAllowed) {if (sThreadLocal. get ()! = Null) {throw new RuntimeException (Only one logoff may be created per thread);} // a new logoff object sThreadLocal is provided here. set (new Looper (quitAllowed);} // sThreadLocal is a static variable static final ThreadLocal
SThreadLocal = new ThreadLocal
();
Logoff has a MessageQueue object that stores the message queue.
final MessageQueue mQueue;
When a Handler sends a Message, the Message will be added to MessageQueue, and the target object of the Message is bound to the Handler. In this way, the Message references the Activity, GC cannot recycle closed activities.
Handler. sendMessage finally calls the following method to send a message, holding the Activity
Public boolean sendMessageAtTime (Message msg, long uptimeMillis) {MessageQueue queue = mQueue; if (queue = null) {RuntimeException e = new RuntimeException (this + sendMessageAtTime () called with no mQueue); Log. w (logoff, e. getMessage (), e); return false;} return enqueueMessage (queue, msg, uptimeMillis);} private boolean enqueueMessage (MessageQueue queue, Message msg, long uptimeMillis) {// here, the message holds the handler object, and the handler holds Activity msg.tar get = this; if (mAsynchronous) {msg. setAsynchronous (true);} return queue. enqueueMessage (msg, uptimeMillis );}
When Handler is created, it is associated with the logoff object created above, so that the message mechanism can run.
Public Handler (Callback callback, boolean async) {if (FIND_POTENTIAL_LEAKS) {final Class klass = getClass (); // check if the Class is anonymous, a member Class, or a local Class, if it is not a static object, the system will prompt a warning that there is a risk of Memory leakage if (klass. isAnonymousClass () | klass. isMemberClass () | klass. isLocalClass () & (klass. getModifiers () & Modifier. STATIC) = 0) {Log. w (TAG, The following Handler class shoshould be static or leaks might occur: + klass. getCanonicalName () ;}/// retrieve logoff mlogoff = logoff. myLooper (); if (mloexception = null) {throw new RuntimeException (Can't create handler inside thread that has not called loled. prepare ();} mQueue = mloue. mQueue; mCallback = callback; mAsynchronous = async ;}
With the above reasons, we can use the following methods to avoid Memory leakage. Many articles are available on the Internet, which will not be listed here.
1. Use static to declare handler. static classes do not reference external classes.
2. If the Handler must use Activity, use WeakReference to reference it.
3. In the event of Activity termination or suspension, removeMessages or removeCallbacksAndMessages removes messages from the Message Queue (when the above two messages are not met, the Handler has not yet processed the Activity when it is closed, memory leakage)