[Android Memory] App Debug memory leak context (top)

Source: Internet
Author: User

Reprinted from: http://www.cnblogs.com/qianxudetianxia/p/3645106.html

Context, as the most basic contexts, carries the most basic components such as activity,service. When an object is referenced to activity and cannot be reclaimed, it will cause a large range of objects not to be reclaimed and released, thereby causing a memory leak.

Here are some common scenarios for analysis.

1. References to callback objects

Look at the code first:

@Overrideprotectedvoid onCreate (Bundle state) {  superonCreate (state);      =new TextView (this);  Label.settext ("Leaks is bad");     Setcontentview (label);}

Let's see what's wrong with you?

No problem, just keep looking:

 private static  drawable sbackground; @Overrideprotected voidonCreate (Bundle state) {Super. OnCreate (state); TextView label=NewTextView ( This); Label.settext ("Leaks is bad"); if(Sbackground = =NULL) {Sbackground=getdrawable (R.DRAWABLE.LARGE_BITMAP);     } label.setbackgrounddrawable (Sbackground); Setcontentview (label);}

Is there a problem?

Haha, hold on for a moment, first of all, the history of Android release:

/* 2.2        2010-3-20,froyo2.3        2010-12-6, Gingerbread3.0        2011-2-22, Honeycomb4.0        2011-10-11 Ice Cream Sandwich* *

Understanding the history of source code is very useful for us to analyze the Android codes.

OK, start analyzing the code.

First, look at the setbackgrounddrawable (drawable background) method source code inside a line to draw our attention:

 Public void setbackgrounddrawable (drawable background) {    //  ...    Background.setcallback (this);     //  ... ...}

So Sbackground maintains a reference to view, and view maintains a reference to the activity.

When exiting the current activity, the current activity should be released, but since Sbackground is a static variable, its life cycle is not over, and sbackground indirectly keeps a reference to the activity, Causes the current activity object to not be freed, which in turn causes a memory leak.

So the conclusion is: there is a memory leak!

This is an example of an official Android document:http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html

Is this the end of it?

I found online too much direct copy or indirect copy of this article, a search a large, and attracted a large number of Android beginners constantly reprint learning.

But after I deeply analyze drawable source code, things have changed.

This article of the official Android document was written in January 2009, when Android Source was at least froyo.

The implementation of Froyo's drawable Setcallback () method is this:

 Public Final void Setcallback (Callback cb) {        = cb;}

The code in gingerbread is still the same.

But when we enter Honeycomb, which is the code after 3.0, we find that the implementation of the Drawable Setcallback () method becomes:

 Public Final void Setcallback (Callback cb) {        new weakreference<callback>(CB);}

In other words, after 3.0, drawable used a soft reference to fix the leaked example problem. (As for the soft reference how to solve the later there is a chance to analyze it again)

So the final conclusion is that there is a memory leak before android3.0, no memory leaks after 3.0!

If you carefully compare the code, the code before and after the Android3.0 improved a lot of similar code, the previous cursor in the example is also fixed after 3.0.

From this example, we found out how memory was leaked through callbacks , and also learned how to fix a similar memory leak through the official code update.

2. System Service Object

Through a variety of system services, we are able to do some of the system's well-designed bottom-up functions:

//Contextimpl.java@Override PublicObject Getsystemservice (String name) {Servicefetcher Fetcher=system_service_map.get (name); returnFetcher = =NULL?NULL: Fetcher.getservice ( This);} Static{registerservice (Accessibility_service,NewServicefetcher () { PublicObject GetService (Contextimpl ctx) {returnaccessibilitymanager.getinstance (CTX);     }}); Registerservice (Captioning_service,NewServicefetcher () { PublicObject GetService (Contextimpl ctx) {return NewCaptioningmanager (CTX);     }}); Registerservice (Account_service,NewServicefetcher () { PublicObject CreateService (Contextimpl ctx) {IBinder b=Servicemanager.getservice (Account_service); Iaccountmanager Service=IAccountManager.Stub.asInterface (b); return NewAccountmanager (CTX, service);    }}); // ... ...}

These are in fact defined in the context, which is supposed to be the system of services, should be no problem, but the code to the manufacturers a change, things have changed.

Some vendor-defined services, or the manufacturers themselves modified some of the new code caused the system services to reference the context object can not be released in a timely manner, I have encountered the Wifi,storage service has a memory leak.

We can't change these system-level applications, we can only modify our own applications.

The solution is: Use ApplicationContext instead of context.

Let's take an example:

// For exampleMstoragemanager == (StorageManager) getapplicationcontext (). Getsystemservice ( Context.storage_service);

3. Handler objects

Look at the code first:

 Public class extends qactivity {        //  Lint Tip:this Handler class should be static or leaks might occur     Classextends  Handler {        ...    }}

There are two key points for the handler leak:

1). Inner class

2). Life cycle and activity are not necessarily consistent

1th, handler use more, often need to create internal classes in the activity, so this scenario is still a lot of.

The Inner class holds a reference to the external class activity, and when the handler object has a message queued, it cannot be freed, which in turn causes the activity object to not be freed.

If it is declared as static, the inner class does not hold a reference to an external acitivity and does not block the release of the activity object.

If declared as static, a weak reference (WeakReference) can be declared inside it to refer to the external class.

 Public classMainactivityextendsActivity {PrivateCustomhandler Mhandler; @Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate); Mhandler=NewCustomhandler ( This); }     Static classcustomhandlerextends Handler {//internally declares a weak reference, referencing an external class        PrivateWeakreference<mainactivity >activityweakreference;  PublicMyHandler (myactivity activity) {activityweakreference=NewWeakreference<mainactivity >(activity); }                // ... ...       }}

2nd, in fact not only refers to the inner class, but all handler objects, how to solve the above said handler object has a message in the queue, without blocking the activity object release?

The solution is also simple, when the activity OnStop or OnDestroy, cancel the handler object's message and runnable.

by looking at the API for handler, it has several methods: Removecallbacks (Runnable R) and removemessages (int what).

// It's all meant to keep mhandler from getting muddy . @Override  Public void OnDestroy () {    mhandler.removemessages (message_1);    Mhandler.removemessages (message_2);    Mhandler.removemessages (message_3);    Mhandler.removemessages (message_4);      //  ... ...      mhandler.removecallbacks (mrunnable);      //  ... ...}

Is the code above too long? Well, here's the big trick:

@Override  Public void OnDestroy () {    //  If null, all callbacks and messages'll be removed.    Mhandler.removecallbacksandmessages (null);}

Some people will ask, when the activity exits, I have a lot of things to do, how to do? I think there must be a way, such as service and so on.

4. Thread Object

As with handler objects, the life cycle of thread is not necessarily the same as the activity life cycle, as is possible with memory leaks.

And because thread is primarily multi-tasking, it often results in a large number of thread instances.

As a result, the thread object has 2 leak points to note:

1). Create too many thread objects

2). The thread object still executes in the background after activity exits

Solutions are:

1). using Threadpoolexecutor, it is very common to do many asynchronous events at the same time, this does not elaborate.

2). when the activity exits, exit thread.

1th, there are too many examples, we recommend that you refer to the Afinal Asynctask implementation of learning.

2nd, how to exit the thread normally, as I mentioned in the previous blog post. The sample code is as follows:

//refhttp://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.htmlPrivate volatileThread blinker; Public voidStop () {blinker=NULL;}  Public voidrun () {Thread thisthread=Thread.CurrentThread ();  while(Blinker = =thisthread) {        Try{thisthread.sleep (interval); } Catch(Interruptedexception e) {} repaint (); }}

Some people will ask, when the activity exits, I have a lot of things to do, how to do? Take a look at the last line of analysis above handler.

(not to be continued)

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.