How to solve common memory leaks in Android

Source: Internet
Author: User

In the development of Android programs. When an object is no longer needed, it should be recycled. Another object that is being used holds its reference, which causes it to not be recycled. This causes the objects that should be recycled to not be recycled and stuck in the heap memory, and a memory leak occurs.

What is the impact of memory leaks?

It is one of the main causes of the application Oom. Because the Android system allocates limited memory for each application. When a memory leak occurs in an application. It is inevitable that the memory required by the application exceeds the memory limit allocated by the system, which results in a memory overflow and the application crash.

One, the memory leak caused by the single case

   Android的单例模式很受开发人员的喜爱,只是使用的不恰当的话也会造成内存泄漏。

由于单例的静态特性使得单例的生命周期和应用的生命周期一样长,这就说明了假设一个对象已经不须要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。

For example, here's the example:

public   Class  AppManager {private  static     AppManager instance; private     Context context; private  appmanager  (Context context)    {this . Context = context; } public  static  appmanager getinstance  (Context context) {if  (instance! = null ) {instance = new  AppManager (context);    } return  instance; }}

This is a common singleton pattern, when creating this singleton, because of the need to pass in a context. So the length of the life cycle of this context is critical:
1, the incoming is application of the context: this will not matter what problem, because the life cycle of the singleton and application the same length;
2. The context of the activity is passed in: when the corresponding activity of this context exits, the context is as long as the activity's life cycle (activity indirectly inherits from the context). So the current activity exits when its memory is not reclaimed, because the Singleton object holds a reference to the activity.

So the correct singleton should be changed to the following way:

public   Class  AppManager {private  static     AppManager instance; private     Context context; private  appmanager  (Context context)    {this . Context = Context.getapplicationcontext (); } public  static  appmanager getinstance  (Context context) {if  (instance! = null ) {instance = new  AppManager (context);    } return  instance; }}

This will eventually use the context of application regardless of what context is passed in. The life cycle of a singleton is as long as the application, which prevents a memory leak.

Second, non-static internal classes Create a static instance of the memory leak caused by

  有的时候我们可能会在启动频繁的Activity中。为了避免反复创建同样的数据资源。会出现这样的写法:
 Public  class mainactivity extends appcompatactivity {    Private StaticTestresource Mresource =NULL;@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (R.layout.activity_main);if(Mmanager = =NULL) {Mmanager =NewTestresource (); }//...} class Testresource {//...}}

This creates a single instance of a non-static inner class within the activity and uses the singleton data each time the activity is started. Thus, while avoiding the creation of resources repeatedly, this type of writing can cause a memory leak, because the non-static inner class holds the reference to the external class by default, and the non-static inner class is used to create a static instance. The life cycle of the instance is as long as the application, which causes the static instance to hold a reference to the activity, causing the memory resources of the activity not to be recycled properly. The right approach is:
Set the inner class as a static inner class or extract the inner class into a single case, assuming you need to use the context, use ApplicationContext.

Iii. memory leaks caused by handler

     Handler的使用造成的内存泄漏问题应该说最为常见了,平时在处理网络任务或者封装一些请求回调等api都应该会借助Handler来处理,对于Handler的使用代码编写一不规范即有可能造成内存泄漏。例如以下演示样例:
 Public  class mainactivity extends appcompatactivity {    PrivateHandler Mhandler =NewHandler () {@Override         Public void Handlemessage(Message msg) {//...}    };@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);    LoadData (); }Private void LoadData(){//...requestMessage message = Message.obtain ();    Mhandler.sendmessage (message); }}

This way of creating handler causes a memory leak, because Mhandler is an instance of handler's non-static anonymous inner class. So it holds a reference to the external class activity, and we know that Message Queuing is constantly polling for processing messages in a looper thread. Then, when the activity exits, there is an unhandled message in the message queue or a message is being processed. Messages in Message Queuing hold a reference to the Mhandler instance, and Mhandler also holds the activity reference. As a result, the memory resources of the activity cannot be reclaimed in time. Causes a memory leak, so the second approach is:

 Public  class mainactivity extends appcompatactivity {    PrivateMyHandler Mhandler =NewMyHandler ( This);PrivateTextView Mtextview;Private Static  class myhandler extends Handler {        PrivateWeakreference<context> reference; Public MyHandler(Context context) {reference =NewWeakreference<> (context); }@Override         Public void Handlemessage(Message msg) {Mainactivity activity = (mainactivity) reference.get ();if(Activity! =NULL) {Activity.mTextView.setText (""); }        }    }@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);        Mtextview = (TextView) Findviewbyid (R.id.textview);    LoadData (); }Private void LoadData() {//...requestMessage message = Message.obtain ();    Mhandler.sendmessage (message); }}

Create a static handler inner class, and then use weak references to objects held by handler so that the objects held by handler are recycled, even if the activity leaks are avoided. It's just that the message queue in the Looper thread is still a message that is likely to be processed, so we should remove the message from the message queue when the activity is destroy or stop. More accurate practices such as the following:

 Public  class mainactivity extends appcompatactivity {    PrivateMyHandler Mhandler =NewMyHandler ( This);PrivateTextView Mtextview;Private Static  class myhandler extends Handler {        PrivateWeakreference<context> reference; Public MyHandler(Context context) {reference =NewWeakreference<> (context); }@Override         Public void Handlemessage(Message msg) {Mainactivity activity = (mainactivity) reference.get ();if(Activity! =NULL) {Activity.mTextView.setText (""); }        }    }@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);        Mtextview = (TextView) Findviewbyid (R.id.textview);    LoadData (); }Private void LoadData() {//...requestMessage message = Message.obtain ();    Mhandler.sendmessage (message); }@Override    protected void OnDestroy() {Super. OnDestroy (); Mhandler.removecallbacksandmessages (NULL); }}

Use Mhandler.removecallbacksandmessages (null) to remove all messages and all runnable in the message queue. Of course, you can also use Mhandler.removecallbacks () or mhandler.removemessages () to remove the specified runnable and message.

Iv. memory leaks caused by threads
It is also common to have a memory leak caused by threads, such as the following two demo samples, which may have been written by everyone.

//—————— test1        NewAsynctask<Void,Void,Void>() {@Overrideprotected VoidDoinbackground (Void... params) {Systemclock.Sleep10000);return NULL; }        }.Execute ();//—————— test2        New Thread(NewRunnable () {@Override Public voidRun () {Systemclock.Sleep10000); }        }).Start ();

Both the async task and the runnable are an anonymous inner class, so they have an implicit reference to the current activity.

Assuming that the activity is not completed before it is destroyed, the memory resource of the activity cannot be reclaimed, causing a memory leak. The right approach is to use static internal classes. For example, the following:

    Static  class myasynctask extends asynctask<void, void,  Void> {        PrivateWeakreference<context> WeakReference; PublicMyasynctask (Context context) {WeakReference =NewWeakreference<> (context); } @Overrideprotectedvoid Doinbackground (void ... params) {Systemclock.sleep (10000);return NULL; } @Overrideprotected voidOnPostExecute (Void aVoid) {Super. OnPostExecute (AVoid); Mainactivity activity = (mainactivity) weakreference.get ();if(Activity! =NULL) {//...}        }    }Static  class myrunnable implements Runnable{@Override Public voidRun () {Systemclock.sleep (10000); }    }//——————    NewThread (NewMyrunnable ()). Start ();NewMyasynctask ( This). Execute ();

This avoids the memory resource leaks of the activity. Of course, when the activity is destroyed should also cancel the corresponding task Asynctask::cancel (), to avoid tasks in the background to run waste resources.

V. Memory leaks due to resource not shutting down
For the use of braodcastreceiver,contentobserver,file. The use of resources such as cursor,stream,bitmap should be closed or cancelled in time when activity is destroyed. Otherwise, these resources will not be recycled, causing a memory leak.

How to solve common memory leaks in Android

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.