WeakReference 在android中的應用

首先咱們來看一段代碼:java

public class AutoActivity extends Activity {

    Handler handler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            
        };
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auto);
    }
}

       上面這段代碼沒有什麼問題,可是在handler對象建立的時候卻會報警告:This Handler class should be static or leaks might occur意思是:Handlerandroid

類應該爲static類型,不然可能會形成內存泄漏。爲何會形成這種狀況呢?這種狀況就是因爲android的特殊機制形成的:當一個android主線程被創ide

建的時候,同時會有一個Looper對象被建立,而這個Looper對象會實現一個MessageQueue(消息隊列),當咱們建立一個handler對象時,而handler的oop

做用就是放入和取出消息從這個消息隊列中,每當咱們經過handler將一個msg放入消息隊列時,這個msg就會持有一個handler對象的引用。所以當this

Activity被結束後,這個msg在被取出來以前,這msg會繼續存活,可是這個msg持有handler的引用,而handler在Activity中建立,會持有Activity的引用,google

於是當Activity結束後,Activity對象並不可以被gc回收,於是出現內存泄漏。spa

        這個根本緣由就是:Activity在被結束以後,MessageQueue並不會隨之被結束,若是這個消息隊列中存在msg,則致使持有handler的引用,可是又線程

因爲Activity被結束了,msg沒法被處理,從而致使永久持有handler對象,handler永久持有Activity對象,因而發生內存泄漏。可是爲何爲static類型就code

會解決這個問題呢?由於在java中全部非靜態的對象都會持有當前類的強引用,而靜態對象則只會持有當前類的弱引用。聲明爲靜態後,handler將會持對象

有一個Activity的弱引用,而弱引用會很容易被gc回收,這樣就能解決Activity結束後,gc卻沒法回收的狀況。(至於爲何強引用不可以被gc自動回收,而

弱引用對象爲何會被gc回收,能夠自行去google)。

因此解決這個警告就有幾種方法:

一:將hanlder對象聲明爲靜態的對象。

二:使用靜態內部類,經過WeakReference實現對Activity的弱引用。具體實現看如下代碼:

public class AutoActivity extends Activity {
    
    MyHandler handler = new MyHandler(this);
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_auto);
    }
    
    static class MyHandler extends Handler{
        WeakReference<AutoActivity> mactivity;
        
        public MyHandler(AutoActivity activity){
            mactivity = new WeakReference<AutoActivity>(activity);
        }
        
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);            
            switch (msg.what) {
            case 100:                
                //在這裏面處理msg
                //經過mactivity.get()獲取Activity的引用(即上下文context)
                break;                
            default:
                break;
            }
        }
    }
}
相關文章
相關標籤/搜索