Handler引發(fā)的內(nèi)存泄漏

在我們寫代碼的時(shí)候,為了實(shí)現(xiàn)在子線程更新UI的需要,我們會(huì)定義一個(gè)Handler屬性,并聲明一個(gè)匿名內(nèi)部類,重寫handleMessage方法,就像下面這樣。

public class MainActivity extends AppCompatActivity {
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other);
    }
}

那如果細(xì)心看下,其實(shí)Android Studio會(huì)給我一個(gè)提示信息。


意思就是我們應(yīng)該定義一個(gè)靜態(tài)的類,這樣可能會(huì)導(dǎo)致內(nèi)存泄漏。

OK,那這里為什么會(huì)引起內(nèi)存泄漏?首先我們要明白其實(shí)匿名內(nèi)部類或者內(nèi)部類都會(huì)隱形持有外部類的引用,其實(shí)這里Handler就持有MainActivity的引用,在Handler中我們可以隨意調(diào)用MainActivity的方法。在我們發(fā)送消息時(shí)handler會(huì)被復(fù)制給message.target,并放入消息隊(duì)列。但是主線的消息隊(duì)列并不會(huì)隨著Activity的銷毀而銷毀,因此導(dǎo)致Activity的泄漏。那知道了泄漏的原因我們就知道該怎解決了。
1、定義靜態(tài)內(nèi)部類

private static class MyHandler extends Handler{
    private WeakReference<MainActivity> mActivity;

    public MyHandler(MainActivity activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
    }
}

在靜態(tài)內(nèi)部類中持有Activity的弱連接這樣就不會(huì)引發(fā)內(nèi)存泄漏了。但是這樣的話消息隊(duì)列中還是有為處理完的消息,其實(shí)Activity銷毀后,再處理這個(gè)消息已經(jīng)沒有意義了,因此有了第二種方法。
2、onDestory時(shí)清理消息
既然內(nèi)存泄漏是因?yàn)锳ctivity銷毀而消息還在,那我在OnDestory時(shí)把它清理掉不就行了,幸運(yùn)的是Handler提供了這樣的方法:


我們可以直接調(diào)用removeCallbacksAndMessages()方法清理message。
注意:這個(gè)方法并不是清空消息棧中所有的message,而是清理message.target等于這個(gè)handler的message,因此不會(huì)影響到無(wú)關(guān)的message和Handler。
參看下面的MessageQueue.removeCallbacksAndMessages

void removeCallbacksAndMessages(Handler h, Object object) {
    if (h == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;

        // Remove all messages at front.
        while (p != null && p.target == h
                && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容