We all know that in Android development it is easy to cause memory leaks, especially through the log log logs of the cloud, so we must use the Androidlint tool to do some code monitoring, to avoid memory leaks, common memory leaks such as internal classes hold external classes of applications, Causes the object to not be released normally. The following on the Internet interception of two good cases, hereby recorded.
I. Memory leaks caused by handler
When using handler to update the UI, I wrote this:
public class Sampleactivity extends Activity { private final Handler Mleakyhandler = new Handler () { @Override
public void Handlemessage (Message msg) { //TODO }}}
It looks normal, but Android Lint gives a warning:
This Handler class should be static or leaks might occur
In fact, for this problem, Android F Ramework's engineer, Romain, has already explained on the Google Forum, and has given him a suggested wording:
I wrote that debugging code because of a couple of memory leaks I
found in the Android codebase. Like your said, a Message has a
reference to the Handler which, when it's inner and non-static, has a
reference to the outer this (a Activity for instance.) If the Message
lives in the "queue for a" long time, which happens fairly easily when
posting a delayed message for instance, you keep a reference to the
Activity and "leak" all the views and resources. It gets even worse
When you obtain a Message and don ' t post it right away but keep it
somewhere (for instance with a static structure) for later use.
The wording of his suggestion was:
?
Class Outerclass { class Innerclass { private final weakreference<outerclass> mtarget; Innerclass (Outerclass target) { mtarget = new weakreference<outerclass> (target); } void DoSomething () { Outerclass target = Mtarget.get (); if (target! = null) { target.do ();}} }
below, let us explain further:
when the 1.Android app launches, the Android Framework creates a Looper object for the main thread that will run through the app's entire lifecycle, implementing a message queue, and opens a loop to process the message object. The main event of the framework consists of an internal message object that is added to the message queue when these events are triggered.
2. When an handler is instantiated (as in the above), it is associated with the message queue of the main thread Looper object, and the message object that is pushed into the queue of messages will hold a handler reference so that when the looper is processed to this message , the framework executes the handler Handlemessage (Message) method.
3. In the Java language, non-static anonymous inner classes hold an implicit reference to an external class, while static inner classes do not.
public class Sampleactivity extends Activity { private final Handler Mleakyhandler = new Handler () { @Override
public void Handlemessage (Message msg) { //... } } @Override protected void onCreate (Bundle savedinstancestate) { super.oncreate (savedinstancestate); Post a message and delay its execution for ten minutes. Mleakyhandler.postdelayed (New Runnable () { @Override public void Run () {} }, * *); Go back to the previous Activity. Finish (); }}
when activity is dropped, message will be present in the message queue for up to 10 minutes before it is executed. This message holds a reference to handler, and handler also holds an implicit reference to the external class (sampleactivity), which is persisted until the message is executed. This ensures that the context of the activity is not reclaimed by the garbage collection mechanism, but also leaks the resources of the application (Views and Resources).
to solve this problem, handler in the following code is a static anonymous inner class. Static anonymous inner classes do not hold an implicit reference to an external class, so activity will not be compromised. If you need to invoke the external activity method in handler, let handler hold a weakreference to the activity so that the context of the activity is not disclosed, as follows:
public class Sampleactivity extends Activity {/** * Instances of static inner classes does not hold a implicit * ref Erence 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 (Message 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 is "static". */private static final Runnable srunnable = new Runnable () {@Override public void Run () {}}; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Post a message and delay its execution For ten minutes. Mhandler.postdelayed (srunnable, 60 * 10 * 1000); Go back to the previous Activity. Finish (); }}
Summary:
In actual development, if the life cycle of the inner class is inconsistent with the activity's life cycle (for example, after the activity finish () has been waiting for 10 minutes, the instance of the inner class executes), then the non-static inner class is avoided in the activity. In this case, a static inner class is used, while holding an activity-WeakReference.
Reprint Source: http://my.oschina.net/liucundong/blog/294127
Second, the object inside the class holds a reference to the external class
public class Util { private Context mcontext; private static Util sinstance; Private Util (Context context) { This.mcontext = context; } public static Util getinstance (context context) { if (sinstance = = null) { sinstance = new Util (context); } return sinstance; } Other methods}
Suppose activity A uses the Util class:
Util.getinstance (this);
The problem with this code is that, in activity A, the Util class is used, and the context being passed in is actvitiy-context. Imagine that when the activity a life cycle ends, but the Util class still has a reference (Mcontext), so that the memory occupied by activity A is not recycled, and a object is no longer used. I wrote the code test, in a called the Finish (), A's Destroy () method is also executed, but its occupied memory, for example, ImageView occupied memory, or can not be released. If you are interested, you can test it yourself.
So how do we solve this problem? In a, you can use Util.getinstance (Getapplicationcontext ()); or Util.getinstance (Getapplication ()); Replace.
Because the life cycle of the application is throughout the program, the Util class holds its references and does not cause a memory leak problem.
In fact this problem Android official document under the Resources directory of an article titled
Avoiding Memory Leaks
Article has been mentioned.
It looks normal, but Android Lint gives a warning:
This Handler class should is static or leaks might occur
In summary, to avoid context-related memory leaks, remember the following:
- Keep long-lived references to a context-activity (a reference to an activity should has the same life cycle as the Activity itself)
- Try using the context-application instead of a context-activity
- Avoid non-static Inner Classes in an activity if you don't control their life cycle, use a static inner class and make a W Eak reference to the activity inside. The solution to this issue are to use a static inner class with a to the outer class, as do in and its W inner class fo R instance
- A garbage collector is A insurance against memory leaks.
Excerpt from: http://xiechengfa.iteye.com/blog/1413688#bc2348883
Both articles are good, recorded.
This Handler class should is static or leaks might occur
Handler Class should be Static or Leaks occur