Turn from: Memory leak caused by using handler in Android
In activity, a custom handler is often used to handle the message received by the main thread, but after ADT20, there is a hint that the following definition, as defined below, has the risk of a memory leak:
PrivateHandler Mhandle =NewHandler () {@Override Public voidhandlemessage (Message msg) {Switch(msg.what) { Case0: //This is the code Break; default: Break; } Super. Handlemessage (msg); } };
When using the Android Lint tool, you will get this warning, specific tips are as follows:
This Handler class should is static or leaks might occur (com.example.multifragment.sampleactivity.1) issue:ensures th At Handler classes does not hold on to a reference to an outer class Id:handlerleak Since this Handler are declared as an in NER class, it may prevent the outer class from being garbage collected. If the Handler is using a Looper or MessageQueue for a thread and other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follow S:declare the Handler as a static class; In the outer class, instantiate a weakreference to the outer class and pass this object to your Handler when you Instantia Te the Handler; Make all references to the outer class using the WeakReference object.
1. When an Android app starts, it automatically creates a Looper instance that is used by the main thread. The main job of Looper is to handle a message object in a message queue. In Android, all Android frame events (such as activity lifecycle method calls and button clicks) are put into the message and then added to the message queue that looper to process, and the looper is responsible for processing one line at a time. The Looper life cycle in the main thread is as long as the current application.
2. When a handler is initialized on the main thread, we send a target for this handler message to the Looper processing message queue, and the message that has actually been sent already contains a reference to the handler instance. Only then Looper can call Handler#handlemessage (message) to complete the correct handling of the message when it is processed to this message.
3. In Java, non-static inner classes and anonymous inner classes implicitly hold references to their external classes. Static inner classes do not hold references to external classes.
The following example:
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 (); }}
After analyzing the code above, when we perform the activity's finish method, the deferred message will be present in the main thread message queue for 10 minutes before it is processed, and the message contains the handler reference, and handler is an instance of an anonymous inner class. It holds a reference to the outside of the sampleactivity, so this causes the sampleactivity not to be recycled, which leads to sampleactivity holding a lot of resources that cannot be recycled, which is what we often call a memory leak.
Note that the above new runnable is also implemented in the anonymous inner class, which also holds the sampleactivity reference and prevents Sampleactivity from being recycled.
To solve this problem, the idea is not applicable to non-static inner classes, when inheriting handler, either in a separate class file, or using static internal classes. Because static inner classes do not hold references to external classes, they do not cause memory leaks for external class instances. When you need to invoke external activity in a static inner class, we can use a weak reference to handle it. Also on the same need to set runnable to static member properties. Note: A static anonymous inner class instance does not hold a reference to an external class. The code that will not cause a memory leak after modification is as follows
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 (); }}
In fact, many of the memory leaks in Android are caused by the use of non-static internal classes in the activity, as mentioned in this article, so when we use a non-static inner class, we should pay special attention to if its instance holds the object life cycle is greater than its outer class object, Then it is possible to cause a memory leak. Prefer to use static classes of articles and weak references to solve this problem.
In addition to the weak reference method described above, other workarounds: @SuppressLint ("Handlerleak") application issues
First: (not recommended) directly add the comment "@SuppressLint (" Handlerleak ") or retrieve Handlerleak in lint Error checking, and then select Ignore as prompted. Not recommended, this approach does not actually solve the problem.
The second kind: Defines the handler as static, then uses the Post method to transmit the Runnable object to the main thread, this method will send the message to the corresponding Runable object, applies to only one message to send the situation, If there is more than one message to send a method that can take the weak reference above.
Android Handler Leak