Android實戰技巧之三十八:Handler使用中可能引發的記憶體流失,androidhandler

來源:互聯網
上載者:User

Android實戰技巧之三十八:Handler使用中可能引發的記憶體流失,androidhandler
問題描述

曾幾何時,我們用原來的辦法使用Handler時會有下面一段溫馨的提示:

This Handler class should be static or leaks might occur

下面是更詳細的說明(Android Studio上的警告,不知道Eclipse上是否相同)

Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected. If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references to members of the outer class using the WeakReference object.

大概意思就是:

一旦Handler被聲明為內部類,那麼可能導致它的外部類不能夠被記憶體回收。如果Handler是在其他線程(我們通常成為worker thread)使用Looper或MessageQueue(訊息佇列),而不是main線程(UI線程),那麼就沒有這個問題。如果Handler使用Looper或MessageQueue在主線程(main thread),你需要對Handler的聲明做如下修改:
聲明Handler為static類;在外部類中執行個體化一個外部類的WeakReference(弱引用)並且在Handler初始化時傳入這個對象給你的Handler;將所有引用的外部類成員使用WeakReference對象。

解決方案一

上面的描述中基本上把推薦的修改方法明確表達了出來,下面的代碼是我自己使用中的一個實現,請參考:

private CopyFileHandler mHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_appstart);    mHandler = new CopyFileHandler(this);    startCopyDBThread();}private void startCopyFileThread(){    Log.d(TAG, "startCopyDBThread");    new Thread(new Runnable() {        @Override        public void run() {            //DO SOMETHING LIKE: copyDBFile();            Message msg=mHandler.obtainMessage();            mHandler.sendMessage(msg);        }    }).start();}private static class CopyFileHandler extends Handler {    WeakReference<AppStartActivity> mActivity;    public CopyFileHandler(AppStartActivity activity) {        mActivity = new WeakReference<>(activity);    }    public void handleMessage(Message msg) {        final AppStartActivity activity = mActivity.get();       //handle you message here!    }}
為什麼會記憶體流失

那麼為什麼不這樣做會引發記憶體流失呢?
這與幾個關鍵詞有關:內部類、Handler的訊息迴圈(Looper)、Java記憶體回收機制。
需要強調一下,並不是每次使用Handler都會引發記憶體流失,這裡面有一定的幾率,需要滿足特定條件才會引起泄漏。
內部類會有一個指向外部類的引用。
記憶體回收機制中約定,當記憶體中的一個對象的引用計數為0時,將會被回收。
Handler作為Android上的非同步訊息處理機制(好吧,我大多用來進行worker thread與UI線程同步),它的工作是需要Looper和MessageQueue配合的。簡單的說,要維護一個迴圈體(Looper)處理訊息佇列(MessageQueue)。每迴圈一次就從MessageQueue中取出一個Message,然後回調相應的訊息處理函數。

如果,我是說如果,迴圈體中有訊息未處理(Message排隊中),那麼Handler會一直存在,那麼Handler的外部類(通常是Activity)的引用計數一直不會是0,所以那個外部類就不能被記憶體回收。很多人會遇到activity的onDestroy方法一直不執行就是這個原因。

另一個解決方案的嘗試

警告描述中提到了Handler在worker thread中使用Looper或MessageQueue,我嘗試了一下,請大家品鑒。

    private Handler testHandler;    private Thread mThread = new Thread() {        public void run() {            Log.d(TAG,"mThread run");            Looper.prepare();            testHandler = new Handler() {                public void handleMessage(Message msg) {                    Log.d("TAG", "worker thread:"+Thread.currentThread().getName());                    switch (msg.what) {                        //handle message here                    }                }            };            Looper.loop();        }    };    //start thread here    if(Thread.State.NEW == mThread.getState()) {        Log.d(TAG, "mThread name: " + mThread.getName());        mThread.start();    }    //send message here    testHandler.sendEmptyMessage(1);

參考:
http://stackoverflow.com/questions/11407943/this-handler-class-should-be-static-or-leaks-might-occur-incominghandler
http://m.blog.csdn.net/blog/wurensen/41907663
http://blog.csdn.net/lmj623565791/article/details/38377229

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.