1. Overview
existThe ultimate solution to Android memory leaks (Part 1)In this article, we introduce how to check whether an app has memory leaks. This article will summarize the code of typical memory leaks and give corresponding solutions. The main problems of memory leaks can be divided into the following types:
- Memory leak caused by static variables
- Memory leak caused by non-static internal classes
- Memory leak caused by resource not shutting down
2. Memory leak caused by static variables
In java, the life cycle of static variables starts when the class is loaded and ends when the class is unloaded. In other words, in android its life cycle starts when the process starts and ends when the process dies. Therefore, during the run of the program, if the process is not killed, the static variable will always exist and will not be recycled. If a static variable strongly refers to a variable in an Activity, then the Activity will not be released, even if the Activity executes onDestroy (do not equalize the execution of onDestroy with recycled). The solution to this type of problem is: 1. Find a replacement object that is similar to the life cycle of the static variable. 2. If it cannot be found, change the strong quotation method to weak quotation. A relatively typical example is as follows:
Context memory leak caused by singleton
public class IMManager { private Context context; private static IMManager mInstance; public static IMManager getInstance(Context context) { if (mInstance == null) { synchronized () { if (mInstance == null) mInstance = new IMManager(context); } } return mInstance; } private IMManager(Context context) { = context; } }
When getInstance is called, if the passed context is the context of the Activity. As long as this singleton is not released, the activity will not be released.
Solution
Pass the context of Application. Because the life cycle of the Application context is longer than the Activity, it can be understood that the life cycle of the Application context is as long as the life cycle of a singleton, and passing it into it is the most suitable.
public class IMManager { private Context context; private static IMManager mInstance; public static IMManager getInstance(Context context) { if (mInstance == null) { synchronized () { if (mInstance == null) //Convert the passed context into the Application context mInstance = new IMManager(()); } } return mInstance; } private IMManager(Context context) { = context; } }
3. Memory leak caused by non-static internal classes
In java, creating a non-static inner class instance will reference its peripheral instance. If this non-static internal class instance does some time-consuming operations, the peripheral object will not be recycled, resulting in memory leaks. The solution to this type of problem is: 1. Turn the inner class into a static inner class 2. If there is a strong reference to a property in the Activity, change the reference method of the property to a weak reference. 3. When the business allows, these time-consuming tasks are ended when the Activity executes onDestory.
Memory leak caused by internal threads
public class LeakAty extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.aty_leak); test(); } public void test() { //Anonymous internal class will refer to its peripheral instance, so it will cause memory leaks new Thread(new Runnable() { @Override public void run() { while (true) { try { (1000); } catch (InterruptedException e) { (); } } } }).start(); } }
Solution
Modify non-static anonymous internal classes to static anonymous internal classes
public class LeakAty extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.aty_leak); test(); } // Add static to become static anonymous internal class public static void test() { new Thread(new Runnable() { @Override public void run() { while (true) { try { (1000); } catch (InterruptedException e) { (); } } } }).start(); } }
Memory leak caused by Handler
public class LeakAty extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.aty_leak); fetchData(); } private Handler mHandler = new Handler() { public void handleMessage( msg) { switch () { case 0: // Refresh data break; default: break; } }; }; private void fetchData() { //Get data (0); } }
mHandler is an anonymous internal class instance and will refer to peripheral objects. If the Handler still has messages to process when the Activity exits, then this Activity will not be recycled.
Solution
public class LeakAty extends Activity { private TextView tvResult; private MyHandler handler; @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(.aty_leak); tvResult = (TextView) findViewById(); handler = new MyHandler(this); fetchData(); } //The first step is to change the Handler to a static inner class. private static class MyHandler extends Handler { //Second step, change the places where the Activity needs to be referenced into a weak reference. private WeakReference<LeakAty> atyInstance; public MyHandler(LeakAty aty) { = new WeakReference<LeakAty>(aty); } @Override public void handleMessage(Message msg) { (msg); LeakAty aty = atyInstance == null ? null : (); //If the Activity is released and recycled, these messages will not be processed if (aty == null||()) { return; } ("fetch data success"); } } private void fetchData() { // Get data (0); } @Override protected void onDestroy() { //The third step is to remove the callback when the Activity exits (); (null); } }
4. Memory leak caused by unclosed resources
When BraodcastReceiver, Cursor, Bitmap and other resources are used, they need to be released in time when they are not needed. If they are not released, memory leaks will occur.
To sum up, the main situation of memory leaks is the above three types, which ultimately boils down to one point, that is, the resources are not released when they are not needed. Therefore, during the encoding process, you should pay attention to these details to improve the performance of the program.