Solution to memory leak problem caused by handler in Android _java

Source: Internet
Author: User
Tags message queue static class

In common Android programming, handler is often used when doing asynchronous operations and processing return results. This is usually how our code is implemented.

Copy Code code as follows:

public class Sampleactivity extends activity {

Private final Handler Mleakyhandler = new Handler () {
@Override
public void Handlemessage (msg) {
// ...
}
}
}

But, in fact, the above code may cause memory leaks, and when you use the Android Lint tool, you get this warning

Copy Code code as follows:

In Android, Handler classes should is static or leaks might occur, Messages enqueued on the application thread ' s messagequ Eue also retain their target Handler. If The Handler is a inner class, its outer class would be retained as. To avoid leaking the outer class, declare the Handler as a static nested class with a weakreference to its outer class

See here, there may be some confusing, where the code can lead to memory leaks, but also how to cause memory leaks? Let's analyze it slowly.

1. When an Android application starts, it automatically creates a Looper instance that is used by the main thread of the supply. Looper's main job is to process a message object in a message queue. In Android, all of the Android framework events (such as activity lifecycle method calls and button clicks) are put into the message and then added to the message queue Looper to process, which is handled by Looper in one piece. The Looper lifecycle in the main thread is as long as the current application.

2. When a handler is initialized in the main thread, we send a target for this handler message to the Looper processing message queue, the message that has actually been sent already contains a reference to a handler instance. Only in this way looper can call Handler#handlemessage (message) to complete the correct processing of messages when processing the message.

3. In Java, both non-static internal classes and anonymous inner classes implicitly hold references to their external classes. Static internal classes do not hold references to external classes. For this content, you can view the private modifier of the Java: invalid

It is true that the above code example is a bit difficult to detect memory leaks, so the following example is very obvious

Copy Code code as follows:

public class Sampleactivity extends activity {

Private final Handler Mleakyhandler = new Handler () {
@Override
public void Handlemessage (msg) {
// ...
}
}

@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);

Post A and delay its execution for minutes.
Mleakyhandler.postdelayed (New Runnable () {
@Override
public void Run () {/* ... */}
}, 1000 * 60 * 10);

Go back to the previous activity.
Finish ();
}
}

Analyzing the above code, when we perform the activity's finish method, the deferred message will exist in the main thread message queue for 10 minutes before being processed, and the message contains a handler reference, and handler is an instance of an anonymous inner class. It holds a reference to the outside sampleactivity, so this leads to sampleactivity that cannot be recycled, causing many of the resources held by sampleactivity to be recycled, which is what we often call memory leaks.

Note that the new runnable above is also implemented by anonymous inner classes, which also hold sampleactivity references and prevent sampleactivity from being recycled.

To solve this problem, the idea is not to apply non-static internal classes, when inheriting handler, either in a separate class file or using static inner classes. Because static internal classes do not hold references to external classes, they do not cause memory leaks in external class instances. When you need to invoke an external activity in a static inner class, we can use a weak reference to handle it. In addition, you also need to set the runnable to static member properties. Note: A static anonymous inner class instance does not hold a reference to the external class. The code that does not cause a memory leak after modification is as follows:

Copy Code code as follows:

public class Sampleactivity extends activity {

/**
* Instances of static inner classes does not hold a implicit
* Reference to their outer class.
*/
private static class MyHandler extends Handler {
Private final weakreference<sampleactivity> mactivity;

Public MyHandler (sampleactivity activity) {
mactivity = new weakreference<sampleactivity> (activity);
}

@Override
public void Handlemessage (msg) {
Sampleactivity activity = Mactivity.get ();
if (activity!= null) {
// ...
}
}
}

Private final MyHandler Mhandler = new MyHandler (this);

/**
* Instances of anonymous classes does not hold a implicit
* Reference to their outer class when they are "static".
*/
private static final Runnable srunnable = new Runnable () {
@Override
public void Run () {/* ... */}
};

@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);

Post A and delay its execution for minutes.
Mhandler.postdelayed (srunnable, 1000 * 60 * 10);

Go back to the previous activity.
Finish ();
}
}

In fact, many memory leaks in Android are caused by the use of non-static inner classes in activity. As we mentioned in this article, we should be very careful when we use a non-static inner class when we are using it, and if its instance's holding object has a lifecycle greater than its external class object, Then it could lead to a memory leak. Individuals tend to use static classes and weakly referenced methods of the article to solve this problem.

Related Article

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.