The handler class should be static or leaks might occur causes and solutions

Source: Internet
Author: User

Translated from http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html

Use the handler object in the main thread, such as the following code

 Public class extends Activity {  privatefinalnew  Handler () {    @Override      Publicvoid  handlemessage (Message msg) {      //    }  }}

This code generates a hidden memory overflow error, and Android Lint will give an enviable warning:

The handler class should be static or leaks might occur.

But what part of the memory is going to overflow?

To solve this problem, you need to know the background of the Android system:

1. When an Android app launches, the Android system creates a Looper object for the application's main thread. The Looper object implements a simple message queue, which sequentially processes the messages in the loop (Looper). All major application events (such as Activity life cycle, button clicks, etc.) are wrapped as a message entity that is added to the Looper message queue to be processed sequentially. The looper of the main thread exists throughout the lifetime of the application.

2. When an handler object is initialized in the main thread, it is associated to the Looper message queue. When the handler SendMessage () method is called, a Message object is sent to the Looper message queue, and a message sent to the queue of messages will hold a handler reference. The system can then invoke the Handlemessage (message) method of the handler object when Looper processes the message.

3. In Java, non-static (non-static) internal and anonymous classes will hold references to external classes. Conversely, static inner classes do not hold references to external classes.

More Looper,handler-related knowledge can be found in the post-link blog.

After understanding these backgrounds, let's take a look at what's going on inside the overflow, first see the following section of code:

 Public classSampleactivityextendsActivity {Private FinalHandler Mleakyhandler =NewHandler () {@Override Public voidhandlemessage (Message msg) {// ...}} @Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate); //Post a message and delay its execution for ten minutes.Mleakyhandler.postdelayed (NewRunnable () {@Override Public voidRun () {/* ... */ }    }, 1000 * 60 * 10); //Go back to the previous Activity.finish (); }}

When the activity is finished, the deferred message will continue to survive for 10 minutes in the main thread until it is processed. This message holds a reference to the activity's handler object, while the handler is a non-static (non-static) anonymous inner class of activity, so handler holds a reference to the external class that is the activity. Such a reference relationship prevents the activity from being reclaimed by the Java GC and frees the system's resources until the message is processed. In addition, the reference for Yang also exists for anonymous runnable () objects.

The way to solve this problem is to inherit the handler class in a new file, or use a static inner class. Static inner classes do not hold references to external classes, so activity is not compromised. If you need to invoke the method of an external class (here, activiity) in handler, you can make handler have a weak reference to activity (WeakReference) so that the activity is not accidentally leaked.

To solve the problem of memory leaks caused by instantiating an internal anonymous runnable class, we can make the internal anonymous runnable class The static object of the outer class.

 Public classSampleactivityextendsActivity {/*** Instances of static inner classes does not hold a implicit * reference to their outer class. */  Private Static classMyHandlerextendsHandler {Private FinalWeakreference<sampleactivity>mactivity;  PublicMyHandler (sampleactivity activity) {mactivity=NewWeakreference<sampleactivity>(activity); } @Override Public voidhandlemessage (Message msg) {sampleactivity activity=Mactivity.get (); if(Activity! =NULL) {        // ...      }    }  }  Private FinalMyHandler Mhandler =NewMyHandler ( This); /*** Instances of anonymous classes does not hold a implicit * reference to their outer class when they is "static". */  Private Static FinalRunnable srunnable =NewRunnable () {@Override Public voidRun () {/* ... */ }  }; @Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate); //Post a message and delay its execution for ten minutes.Mhandler.postdelayed (srunnable, 1000 * 60 * 10); //Go back to the previous Activity.finish (); }}

When instantiating an inner class in activity, an inner class cannot be non-static if the inner class can survive beyond the activity's lifetime. This situation should use static interiors and hold weak references to external class objects.

RELATED links:

Http://www.cnblogs.com/codingmyworld/archive/2011/09/12/2174255.html

The handler class should be static or leaks might occur causes and solutions

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.