Memory leakage caused by Handler in Android

Source: Internet
Author: User

Memory leakage caused by Handler in Android

In common Android programming, Handler is often used to perform asynchronous operations and process returned results. Our code is usually implemented in this way.

 
 
  1. public class SampleActivity extends Activity { 
  2.  
  3.   private final Handler mLeakyHandler = new Handler() { 
  4.     @Override 
  5.     public void handleMessage(Message msg) { 
  6.       // ...  
  7.     } 
  8.   } 

However, the above Code may cause memory leakage. When you use the Android lint tool, you will receive such a warning.

In Android, Handler classes shoshould be static or leaks might occur, Messages enqueued on the application thread's MessageQueue also retain their target Handler. if the Handler is an inner class, its outer class will be retained as well. to avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class

We can see that there may still be some unclear information, where may cause memory leakage in the code, and how can it cause memory leakage? Let's take a closer look.

1. When an Android Application is started, a logoff instance that is used by the main thread is automatically created. Logoff processes message objects in message queues one by one. In Android, all Android framework events, such as Activity life cycle method calls and button clicks, are put into the message and then added to the Message Queue to be processed by logoff, logoff is responsible for processing data one by one. The logoff lifecycle in the main thread is as long as that of the current application.

2. when a Handler is initialized in the main thread, we send a message whose target is the Handler to The logoff message queue, in fact, a sent Message contains a reference of a Handler instance. Only in this way can logoff call Handler # handleMessage (Message) to complete correct Message processing when processing the Message.

3. in Java, non-static internal classes and anonymous internal classes both implicitly hold references to their external classes. Static internal classes do not hold external class references. For details, see the Java: "invalid" private modifier.

Indeed, the above sample code is a little hard to detect memory leaks, so the following example is very obvious.

 
 
  1. public class SampleActivity extends Activity { 
  2.  
  3.   private final Handler mLeakyHandler = new Handler() { 
  4.     @Override 
  5.     public void handleMessage(Message msg) { 
  6.       // ... 
  7.     } 
  8.   } 
  9.  
  10.   @Override 
  11.   protected void onCreate(Bundle savedInstanceState) { 
  12.     super.onCreate(savedInstanceState); 
  13.  
  14.     // Post a message and delay its execution for 10 minutes. 
  15.     mLeakyHandler.postDelayed(new Runnable() { 
  16.       @Override 
  17.       public void run() { /* ... */ } 
  18.     }, 1000 * 60 * 10); 
  19.  
  20.     // Go back to the previous Activity. 
  21.     finish(); 
  22.   } 

Analyze the code above. When we execute the Activity finish method, delayed messages will exist in the main thread message queue for 10 minutes before being processed, this message contains the reference of Handler, while Handler is an anonymous internal class instance, which holds the reference of SampleActivity outside, so SampleActivity cannot be recycled, as a result, many resources held by SampleActivity cannot be recycled. This is what we often call Memory leakage.

Note that the new Runnable mentioned above is implemented by an anonymous internal class. It also holds a reference to SampleActivity and prevents SampleActivity from being recycled.

To solve this problem, the idea is that non-static internal classes are not applicable. When Handler is inherited, they are either stored in a separate class file or static internal classes. Because static internal classes do not hold external class references, they do not cause memory leakage of external class instances. When you need to call an external Activity in a static internal class, we can use weak references for processing. In addition, you also need to set Runnable to static member attributes. Note: A static anonymous internal class instance does not hold external class references. The modified code will not cause memory leakage:

 
 
  1. public class SampleActivity extends Activity { 
  2.  
  3.   /** 
  4.    * Instances of static inner classes do not hold an implicit 
  5.    * reference to their outer class. 
  6.    */ 
  7.   private static class MyHandler extends Handler { 
  8.     private final WeakReference<SampleActivity> mActivity; 
  9.  
  10.     public MyHandler(SampleActivity activity) { 
  11.       mActivity = new WeakReference<SampleActivity>(activity); 
  12.     } 
  13.  
  14.     @Override 
  15.     public void handleMessage(Message msg) { 
  16.       SampleActivity activity = mActivity.get(); 
  17.       if (activity != null) { 
  18.         // ... 
  19.       } 
  20.     } 
  21.   } 
  22.  
  23.   private final MyHandler mHandler = new MyHandler(this); 
  24.  
  25.   /** 
  26.    * Instances of anonymous classes do not hold an implicit 
  27.    * reference to their outer class when they are "static". 
  28.    */ 
  29.   private static final Runnable sRunnable = new Runnable() { 
  30.       @Override 
  31.       public void run() { /* ... */ } 
  32.   }; 
  33.  
  34.   @Override 
  35.   protected void onCreate(Bundle savedInstanceState) { 
  36.     super.onCreate(savedInstanceState); 
  37.  
  38.     // Post a message and delay its execution for 10 minutes. 
  39.     mHandler.postDelayed(sRunnable, 1000 * 60 * 10); 
  40.  
  41.     // Go back to the previous Activity. 
  42.     finish(); 
  43.   } 

In fact, many memory leaks in Android are caused by the use of non-static internal classes in the Activity, as mentioned in this Article, therefore, when using non-static internal classes, pay special attention to them. If the life cycle of the objects held by the instance is greater than that of the external class objects, memory leakage may occur. I personally prefer to use static classes and weak references to solve this problem.

Translation information

  • How to Leak a Context: Handlers & Inner Classes

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.