(Original) Several solutions to memory leaks

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

 

 

Guess you like

Origin blog.csdn.net/Android_xiong_st/article/details/107403839