Android Memory optimization--static use

Source: Internet
Author: User
<span id="Label3"></p><p><p>In Android development, we often use static to decorate our member variables, which is intended to allow multiple objects to share a single piece of space, save memory, or use a singleton pattern that allows the class to produce only one instance and use it throughout the app. however, improper use at some point or programming irregularities can cause memory leaks (memory Leaks in Java refer to memory not being recovered in a timely manner by gc, resulting in excessive memory consumption)</p></p><p><p>In this paper, we mainly analyze the memory leak caused by the improper reference of the static variable to activtiy, because the system will regenerate the object of the activity (standard Mode) for the same activity page every time it is opened. And each activity object generally contains a large number of view objects and bitmap objects, if the previous activity object can not be collected in a timely manner, resulting in a memory leak Phenomenon.</p></p><p><p>Look at the code and explain it on the following Side.</p></p>The singleton mode does not get the context correctly<pre class="brush:js;toolbar:false;"><pre class="brush:js;toolbar:false;">public class Loginmanager {private context context;    private static Loginmanager manager; public static Loginmanager getinstance (context Context) {if (manager = = Null) Manager = new Loginmanage        R (context);    Return manager;    } private Loginmanager (context Context) {this.context = context; }</pre></pre><p><p>In the Loginactivity</p></p><pre class="brush:js;toolbar:false"><pre class="brush:js;toolbar:false">public class Loginactivity extends Activity {private loginmanager loginmanager;        @Override protected void onCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (r.layout.activity_login);    Loginmanager = Loginmanager.getinstance (this); }</pre></pre><p><p>In this way, you should understand the problem at a glance, in Loginmanager's Singleton context holds the loginactivity this object, even after the successful login we jump to the other activity page, The object of loginactivity is still not recycled because he is holding the case, and the life cycle of the singleton is consistent with Application.</p></p><p><p>The right way to get the context</p></p><pre class="brush:js;toolbar:false"><pre class="brush:js;toolbar:false">public class Loginmanager {private context context;    private static Loginmanager manager; public static Loginmanager getinstance (context Context) {if (manager = = Null) Manager = new Loginmanage        R (context);    Return manager;    } private Loginmanager (context Context) {this.context = Context.getapplicationcontext (); }</pre></pre><p><p>The modification method is also very simple we in the context no longer hold activity context but hold application context, because application is a singleton, so there will be no memory leak Phenomenon.</p></p>Holding activity objects through an inner class in Singleton mode<p><p>The first way the memory leaks too much and obviously, I believe that we will not make such a mistake, the next introduction of this leakage method will be less easy to find, the use of internal classes cause the Activity object is held by the Example.</p></p><p><p>Or look at the code re-analysis, here is a singleton class:</p></p><pre class="brush:js;toolbar:false">public class testmanager {    public static final  Testmanager instance = new testmanager ();    private list< Mylistener> mlistenerlist;    private testmanager ()  {         mListenerList = new ArrayList<MyListener> ();     }    public static testmanager getinstance ()  {         return INSTANCE;    }     Public void registerlistener (mylistener listener)  {         if  (!mlistenerlist.contains (listener))  {             mlistenerlist.add (listener);        }     }   &Nbsp;public void unregisterlistener (mylistener listener)  {         mlistenerlist.remove (listener);     }}interface mylistener {     public void onsomethinghappen ();}</pre><p><p>Then the Activity:</p></p><pre class="brush:js;toolbar:false"><pre class="brush:js;toolbar:false">public class Testactivity extends appcompatactivity {private mylistener mmylistener=new mylistener () {@Overrid    E public void Onsomethinghappen () {}};    Private Testmanager testmanager=testmanager.getinstance ();        @Override protected void onCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (r.layout.activity_test);    Testmanager.registerlistener (mmylistener); }}</pre></pre><p><p>We know that in java, objects of non-static inner classes will hold references to external class objects, so we mmylistener the inner class object to the singleton, sometimes because Mmylistener references our activity object, therefore, the Activity object can not be recycled, resulting in a memory leak Phenomenon.</p></p><p><p>Modify the above code to avoid memory leaks and add the following code to the Activity: '</p></p><pre class="brush:js;toolbar:false"><pre class="brush:js;toolbar:false">@Overrideprotected void OnDestroy () {testmanager.unregisterlistener (mmylistener); Super.ondestroy ();}</pre></pre>Asynctask memory leaks due to improper use<p><p><span class="wmd-input-section"><span class="token lf"><span class="token lf">After describing the memory leaks in both cases, we are looking at a more easily overlooked memory leak, a memory leak caused by improper use of Asynctask.</span></span></span></p></p><pre class="brush:js;toolbar:false"><pre class="brush:js;toolbar:false">Mtask=new asynctask<string,void,void> () {@Overrideprotected Void doinbackground (String ... params) {//        Dosamething.        Return null; }}.execute ("a task");</pre></pre><p><p>Generally we open an asynchronous task in the main thread by implementing an inner class that inherits from the Asynctask class and then implements its corresponding method, then the natural Mtask holds a reference to the activity instance Object. Looking at the implementation of asynctask, we queue our task through a Serialexecutor serial line pool, and this Serialexecutor object is a static final Constant.</p></p><p><p>The specific citation relationship Is:</p></p><p><p>1. Our task is encapsulated in a Futuretask object (it acts as a runable), and the implementation of Futuretask is implemented by an inner class, so it is also for holding Asynctask objects, The Asynctask object refers to the activity object, so the activity object is indirectly referenced by the Futuretask Object.</p></p><p><p>2.futuretask objects are added to an mtasks instance of a Arraydeque-type task queue</p></p><p><p>The 3.mTasks task queue is also held by the Serialexecutor object, which has just said that the Serialexecutor object is a static final Constant.</p></p><p><p>The implementation of the specific asynctask you can refer to its source code, I am here to describe the implementation of its task to add the process can be, in short, analyzed so much through the layers of reference to our activity will be referenced by a static variable. So we should not be in the use of asynctask in which too time-consuming operation, assuming that the activity has exited, but the Asynctask task has not been completed or is still queued for execution, will cause our activity object to be recycled time delay, Memory share becomes larger over Time.</p></p><p><p></p></p><p><p>Workaround the Cancel () function should be called when the activity exits</p></p><pre class="brush:js;toolbar:false"><pre class="brush:js;toolbar:false">@Overrideprotected void OnDestroy () {//mtask.cancel (false);    Mtask.cancel (true); Super.ondestroy ();}</pre></pre><p><p>The specific cancel () pass True or false depending on the actual situation:</p></p><p><p>1. When our task is still queued and not executed, the call to cancel () either True or false, the task is removed from the queued queue, i.e. the task is not Executed.</p></p><p><p>2. When our task has already started (doinbackground is called), the incoming parameter is false and does not interrupt the execution of doinbackground, when the passed parameter is true, if our thread is dormant or blocked (for example: sleep,wait) Condition is interrupted by its execution.</p></p><p><p>Here is a specific explanation of the meaning of cancle (true):</p></p><pre class="brush:js;toolbar:false">Mtask=new asynctask<string,void,void> ()         {@ Overrideprotected void doinbackground (string... params)  {         try {        thread.sleep (10000);         } catch  (interruptedexception e)  {         e.printstacktrace ();        }  &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;LOG.D ("test",  "task is running");         return null;        }         }.execute ("a task");         Try {        //guaranteed Task Execution          thread.sleep ( &nbs);p;      } catch  (interruptedexception e)  {         e.printstacktrace ();        }         mtask.cancel (true);</pre><p><p>In this case our thread is in hibernation call Cancel (true) method will interrupt Doinbackground execution--that is, The output of the log statement will not be Seen.</p></p><p><p>But in this case, I can't break it.</p></p><pre class="brush:js;toolbar:false">Mtask=new asynctask<string,void,void> ()         {@ Overrideprotected void doinbackground (string... params)  {         Boolean loop=true;        while  (LOOP) &NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;LOG.D ("test",  "task is running");         }        return null;         }        }.execute ("a  task ");        try {         thread.sleep (;        } catch ) ( Interruptedexception e)  {        e.printstacktrace ();         }&nbsP;       mtask.cancel (true); </pre><p><p>It is not possible to interrupt the execution of Doinbackground because our thread is not in a wait or hibernate state in a timely manner (true): the log function has been printed Out.</p></p><p><p>Workaround:</p></p><pre class="brush:js;toolbar:false">Mtask=new asynctask<string,void,void> ()         {@ Overrideprotected void doinbackground (string... params)  {         //dosomething.         Boolean loop=true;         while  (loop)  {        if (iscancelled ())          return null;         LOG.D ("test",  "task is running");        }         return null;        }         }.execute ("a task");         try {        thread.sleep (;    )     } catch  (interruptedexception e)  {         e.printstacktrace ();        }         mtask.cancel (true);</pre><p><p>Here we pass in each loop is to check whether the task has been cancle off, if yes then exit. So for Asynctask we also have to pay attention to the correct way to use, otherwise it will also cause a program memory leak Phenomenon.</p></p><p><p>The above is what we need to do to optimize memory use when using static, of course, for the above 3 cases is the use of static in our programming often encountered memory leaks, but there are still a lot of things we are not easily aware Of. For example, If you do not introduce, the third situation above is difficult to detect, then our ultimate memory leak optimization method is: using the memory leak analysis tool, in the next article I will refer to the third case (asynctask) caused by the memory leak, by using the Mat tool for analysis, Explain how the mat is used to troubleshoot memory leaks.</p></p><p><p></p></p><p><p>Android Memory optimization--static use</p></p></span>

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.