Bits and pieces of things are not always remembered for a long time, just learning other people’s articles is just the residue left by others after chewing. I accidentally found this daily interview question, and I thought that if I just thought about it simply, I would not only have little effect, but even I might be too lazy to think about the difficult questions and could not stick to them. So write down every thought, understanding, and other people’s insights. Not only deepen your understanding, but also motivate yourself to stick to it.

Handler function

That’s what the SDK documentation says.

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

That’s what we’re used to updating the UI thread. Handler +Message+Loop+MessageQueue

But if you create a handler object and then override the internal handlerMessage method, AS will alert you to the possibility of a memory leak.

Why is there a memory leak

Android memory leak: An object that needs to be reclaimed by the GC cannot be reclaimed because it is held by a reference to another living object. Then this piece of memory will be occupied for a long time during the running of the program, resulting in the waste of system memory, so that the system runs slowly or even crashes.

So when does a handler cause a memory leak?

Sending delayed messages

As you know, anonymous inner classes hold references to external classes, so handler objects hold references to activity objects. Handler sends a message to MessageQueue, message holds a reference to handler, and MessageQueue holds a reference to Message, MessageQueue belongs to TLS (ThreadLocalStorage) thread and is a different life cycle from Activity.

So when the Activity’s life cycle ends and there are still unprocessed messages in the MessageQueue, the sequence of references above does not allow the Activity objects to be reclaimed, causing a memory leak.

The solution

Knowing that memory leaks are caused by the chain of references, the solution is to break the chain of references above.

The first is the type of reference, there are strong references, soft references, weak references, virtual references, the above reference chain is all strong references.

So the first way is to customize a static inner class. If you want to use methods from an external class, introduce an Activity object through a weakly referenced method.

public class BaseActivity extends Activity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public void myHandleMessage(Message msg){}

    static class MyHandler extends Handler{
        WeakReference<BaseActivity> mActivityReference;
        public MyHandler(BaseActivity activity){
            mActivityReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            BaseActivity activity = mActivityReference.get();
            if(activity ! =null){ activity.myHandleMessage(msg); }}}}Copy the code

You can customize Myahndler objects in BaseActivity, create Myahndler objects in other activities, and override the myHandleMessage method for message handling.

This method handles references between activities and handlers, which can be reclaimed during GC.

The second is to handle subsequent references. Since there are unprocessed messages when the Activity is about to be reclaimed, it is ok to clear the messages when the Activity is about to be reclaimed.

@Override
    protected void onDestroy(a) {
        super.onDestroy();
        if(mHandler ! =null){
            mHandler.removeCallbacksAndMessages(null); }}Copy the code