1. 程式人生 > >Android-This Handler class should be static or leaks might occur

Android-This Handler class should be static or leaks might occur

今天遇到的問題,mark一下

錯誤提示:

This Handler class should be static or leaks might occur 
(全類名)

Issue: Ensures that Handler classes do not hold on to a reference to an outer class
Id: HandlerLeak

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類的應用。如果Handler是個內部類,那 麼它也會保持它所在的外部類的引用。為了避免洩露這個外部類,應該將Handler宣告為static巢狀類,並且使用對外部類的弱應用。

第一種方法:把Handler定義成static,然後用post方法把Runnable物件傳送到主執行緒,程式碼如下:

private TextView tvName;
private static Handler myHandler;
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvName = (TextView) findViewById(R.id.tv_name);
        myHandler=new Handler();
        myHandler.post(myRunnable);//使用handler將Runnable放到主執行緒執行
        }

    Runnable myRunnable=new Runnable() {
        @Override
        public void run() {
            //將原來handler中要做的操作放到Runnable中
            tvName.setText("Demo");
        }
    };

這種方法將要執行的操作放到了Runable物件中,再將Runable放到主執行緒執行,此方法適用於只有一個訊息要傳送的情況。

第二種方法:先定義一個static的內部類MyHandler繼承Handler類,然後讓它持有Activity的弱引用,程式碼如下:

private TextView tvName;
    private static MyHandler myHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvName = (TextView) findViewById(R.id.tv_name);
        myHandler = new MyHandler(this);
        myHandler.sendEmptyMessage(1);
    }

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

        public MyHandler(MainActivity mainActivity) {
            this.reference = new WeakReference<MainActivity>(mainActivity);// 給弱引用賦值
        }

        @Override
        public void handleMessage(Message msg) {
            MainActivity  mainActivity=reference.get();//獲取到引用的Activity
            if (mainActivity == null) {//判斷下看Activity是否被回收
                return;
            }
            switch (msg.what) {//根據不同的訊息執行不同的程式碼
            case 0:
                mainActivity.tvName.setText("Demo");
                break;
            case 1:
                mainActivity.tvName.setText("Test");
                break;
            }
            super.handleMessage(msg);
        }
    }