Android development, memory optimization is a very important issue, today I will give a more detailed introduction to this issue
Before talking about memory optimization, we must first clarify the memory environment problem
The memory environment in java is divided into three types
Stack: used to store references to basic data types and objects
Heap: used to store created objects or arrays, managed by GC, and shared by all threads
Method area: also called static area, contains static variables and class objects, shared by all threads
The cause of memory leak can be divided into the following two situations
1. When an object is no longer needed and is ready to be recycled, another object holds a reference and cannot be recycled
2. Some objects have only a limited life cycle and are still referenced when the life cycle should end.
The accumulation of memory leaks will cause memory overflow. OOM
Next, I will talk about several common memory leak situations and treatment methods:
1. Memory leak caused by singleton
First look at the following code, which is a simple singleton pattern
public class SingerDemo {
private Context context;
private static SingerDemo instance;
private SingerDemo(Context context) {
this.context = context;
}
public static SingerDemo getInstance(Context context) {
if (instance == null) {
instance = new SingerDemo(context);
}
return instance;
}
}
In the singleton construction method, a Context object will be passed in
If we pass in the Activity Context, when the Activity is closed, the singleton object still holds the reference to the Activity
Which leads to a memory leak
The solution is to deal with it in the singleton construction method
Use getApplicationContext() to get the Context of the application
The specific code is as follows
private SingerDemo(Context context) {
// this.context = context;
this.context = context.getApplicationContext();
}
This example also tells us that when using Context, we must pay attention to distinguish the situation.
2. Memory leaks caused by creating static instances of non-static inner classes
Look at the following code
public class MainActivity extends AppCompatActivity {
private static MainClass mainClass = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (mainClass == null) {
mainClass = new MainClass();
}
}
private class MainClass {
}
}
In this case, the non-static inner class MainClass holds a reference to MainActivity by default
As a result, his static instance object always holds a reference to Activity
Cannot be released when Activity is closed
As a result, MainClass cannot be reclaimed by memory, resulting in a memory leak
Solution
Change the inner class to a static inner class
3. Memory leak caused by handler
The life cycle of Handler and the life cycle of Activity are inconsistent,
So when Activity is closed
Handler may still have memory
Look at the following example
public class MainActivity extends AppCompatActivity {
private final Handler myhandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myhandler.postDelayed(new Runnable() {
@Override
public void run() {
}
}, 1000 * 60 * 10);
}
}
When the Handler delays the execution of the message, close the Activity
At this time Handler holds the object of Activity
Caused a memory leak
There are two solutions, the first
When the Activity is closed, remove the Handler message
removeMessages: remove a single message
removeCallbacksAndMessages: remove all messages and callbacks
Another way
1. Declare the handler as static
2. Introduce Activity through weak references,
Operate related methods and View
code show as below:
private static class MyHandler extends Handler {
private WeakReference<MainActivity> mWeakReference;
public MyHandler(MainActivity activity) {
mWeakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity mainActivity = mWeakReference.get();
switch (msg.what) {
case 0x001:
if (mainActivity != null) {
mainActivity.mTextView.setText(msg.obj + "");
}
break;
default:
break;
}
}
}
4. Memory leaks caused by threads
Memory leaks caused by threads are handled in the same way as Handler
Thread and Runnable
Are declared as static
Obtain the Activity object by weak reference
Or in the right life cycle,
To end this thread
5. Memory leak caused by Webview
There are many reasons for Webview to cause memory leaks
Sometimes it’s necessary to handle it on the mobile and web
Here is a solution
1. Put the Activity where the Webview is located in a separate process
Add the android:process="" attribute to the configuration list of Activity
The value of the process attribute is the name of your process
2. When closing the Activity, call the following method to kill the process
android.os.Process.killProcess(android.os.Process.myPid());
For more solutions, please refer to this article
WebView memory leak-solution summary
Finally, share a few points about memory optimization
1. Frequent string splicing uses StringBuilder instead of String
2. ArrayMap, Sparse instead of HashMap
3. Do not create and recycle a large number of objects frequently to avoid memory jitter
Because in the process of calling GC, other processes will be stopped
Once there are too many objects to be processed, it will cause problems such as UI freeze
4. Reuse the resources that come with the system, the reuse of ListView items, etc.
5. Avoid creating objects in the onDraw method
6. Close the Cursor object in time
7. Registration and unregistration should appear in pairs. Such as broadcast registration and cancellation