[Android Memory] App Debug Memory leak context chapter (bottom)

Source: Internet
Author: User

Reprint Address: http://www.cnblogs.com/qianxudetianxia/p/3655475.html

5. Asynctask Objects

I went to a grand trial n years ago, when the interviewer strongly recommended that I use asynctask and other systems to do things, of course, it's understandable.

But Asynctask does need extra attention. Its leakage principle is similar to the previous Handler,thread leakage principle, its life cycle and activity is not necessarily consistent.

The solution is to terminate the background task in Asynctask when the activity exits.

But how does the problem end?

The asynctask provides the corresponding Api:public final Boolean cancel (Boolean mayinterruptifrunning).

Its description has such a sentence:

// attempts to cancel execution of this task.  This attempt would fail if the task has already completed, already been cancelled, or could is cancelled for some other Reason. // If successful, and this task have not started when cancel is called, the this task should never run. If The task has already started and then the mayinterruptifrunning parameter determines whether the thread executing this TAS K should is interrupted in a attempt to stop the task.

Cancel is not necessarily successful, and if it is running, it may break the background task. How does it feel that this is so unreliable?

Yes, it's just not reliable.

So, how can we be more reliable? Let's take a look at the official example:

Private classDownloadfilestaskextendsAsynctask<url, Integer, long> {     protectedLong doinbackground (URL ... urls) {intCount =urls.length; LongTotalSize = 0;  for(inti = 0; I < count; i++) {totalsize+=Downloader.downloadfile (Urls[i]); Publishprogress ((int) ((I/(float) count) * 100)); //Escape Early if cancel () is called//Note that the following line, if cancel is detected, exits in a timely manner             if(IsCancelled ()) Break; }         returntotalsize; }      protected voidOnprogressupdate (Integer ... progress) {setprogresspercent (progress[0]); }      protected voidOnPostExecute (Long result) {ShowDialog ("Downloaded" + result + "bytes"); } }

The official example is very good, in the background loop to listen to the cancel state at all times to prevent the absence of timely exit.

To remind you, Google deliberately in Asynctask's instructions put down a large section of English:

// Asynctask is designed to being a helper class around Thread and Handler and does not constitute a generic threading Fram Ework. Asynctasks should ideally is used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it's highly recommended you use the various APIs provided B Y the java.util.concurrent pacakge such as Executor, Threadpoolexecutor and Futuretask.

Pity me. The continent of China is vast, vast and abundant, and nothing is lacking, which is lack of sensitivity to English reading.

The Asynctask is suitable for short time-consuming operations up to a few seconds. If you want to take a long time to operate, use the APIs under other java.util.concurrent packages, such as executor, Threadpoolexecutor, and Futuretask.

Learn English well and avoid stepping on the pit!

6. Broadcastreceiver Objects

... has leaked intentreceiver ... Is missing a call to Unregisterreceiver ()?

This is directly said, for various reasons did not call to the unregister () method.

The workaround is simple, which is to ensure that the unregister () method is called .

Incidentally, I encountered the opposite situation in the work, receiver object did not Registerreceiver () success (not called), so unregister prompt error:

// java.lang.IllegalArgumentException:Receiver not registered ...

There are two types of solutions:

Scenario One: Set a flag after Registerreceiver () to determine whether unregister () is based on flag. Almost all of the articles on the internet have been written like this, and I have encountered this kind of bug before. But there is no denying that this code looks a bit ugly indeed.

Scenario Two: I later overheard a Daniel reminds me, in the Android source code to see a more general wording:

// just sample, can be written to the tool class // At first glance I see this code, by, too rough, but back to think, want is so simple rough, do not make some simple things so complicated.  privatevoid  Unregisterreceiversafe (broadcastreceiver receiver) {    try {        getcontext (). Unregisterreceiver (receiver);     Catch (IllegalArgumentException e) {        //  ignore    }}

7. TimerTask Objects

TimerTask objects are extremely prone to memory leaks when used in conjunction with the schedule () method of the timer.

Private voidStarttimer () {if(Mtimer = =NULL) {Mtimer=NewTimer (); }      if(Mtimertask = =NULL) {Mtimertask=NewTimerTask () {@Override Public voidrun () {//Todo            }         }; }      if(Mtimer! =NULL&& Mtimertask! =NULL) Mtimer.schedule (Mtimertask,1000, 1000); } 

The point of disclosure is to forget to cancel the timer and TimerTask instances. Cancel is the right time for the cursor to cancel at the appropriate time.

Private void Canceltimer () {         ifnull) {             mtimer.cancel ();              NULL ;         }          if NULL ) {             mtimertask.cancel ();              NULL ;         }    }

8. Observer object.

The disclosure of observer objects is also a common, easy-to-find, easy-to-resolve type of leakage.

First look at a normal code:

//In fact, it is very simple, but contentobserver is a systematic example, it is necessary to come out alone to remind everyone, not lightlyPrivate FinalContentobserver Msettingsobserver =NewContentobserver (NewHandler ()) {@Override Public voidOnChange (BooleanSelfchange, Uri Uri) {        //Todo    }}; @Override Public voidOnStart () {Super. OnStart (); //Register the Observergetcontentresolver (). Registercontentobserver (Settings.Global.getUriFor (XXX),false, msettingsobserver);} @Override Public voidOnStop () {Super. OnStop (); //Unregister it when stopinggetcontentresolver (). Unregistercontentobserver (Msettingsobserver);}

After reading the example, let's take a look at the patient:

 private  final  implements   Observer { public   update (Observable O, Object Arg) { //  Todo ...  }} mcontentquerymap  = new  Co Ntentquerymap (Mcursor, Settings.System.XXX, true , null  ); Mcontentquerymap.addobserver ( new  settingsobserver ()); 

Depend on, who is so lazy, put settingobserver an anonymous object to pass in, this can be how good?

So, some lazy can not be stolen, some of the grammatical sugar is not edible.

The solution is to Delete The Observer when it is not needed or exited.

PrivateObserver msettingsobserver; @Override Public voidOnresume () {Super. Onresume (); if(Msettingsobserver = =NULL) {Msettingsobserver=NewSettingsobserver (); } mcontentquerymap.addobserver (Msettingsobserver);} @Override Public voidOnStop () {Super. OnStop (); if(Msettingsobserver! =NULL) {mcontentquerymap.deleteobserver (msettingsobserver); } mcontentquerymap.close ();}

Note that different registration methods, different anti-registration methods.

// just a reference, not rigid /* addcallback             <==>     removecallbackregisterreceiver        <==>     Unregisterreceiveraddobserver             <==>     deleteobserverregistercontentobserver <==>     Unregistercontentobserver ... */

9. Dialog objects

android.view.windowmanager$badtokenexception:unable to add window-token [email protected] was not valid; Is your activity running?

The message that normally occurs in handler is queued, activity has exited, and then handler starts to deal with dialog related things.

The key point is, how to judge activity is exited, some people say, set a flag in OnDestroy. I regret to tell you that this error is likely to come out.

The solution is to use Isfinishing () to determine whether activity exits.

Handler Handler =NewHandler () { Public voidhandlemessage (Message msg) {Switch(msg.what) { CaseMessage_1://isfinishing = = True, then do not process, end as soon as possible            if(!isfinishing ()) {                //Do not exit//Removedialog ()//ShowDialog ()            }               Break; default:             Break; }          Super. Handlemessage (msg); }  };

Early and early release!

10. Other objects

To listener object-oriented, " put yourself in, remember to be sure to put yourself out in time ."

11. Summary

Combining the context of this article with the previous cursor, we enumerate a large number of leaked instances, and most of the root causes are similar.

By analyzing these examples, we should be able to understand the memory leaks of app layer 90%.

As for how to find and locate memory leaks, this is another interesting topic, now can only say, there are methods have tools.

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.