android This Handler class should be static or leaks might occur

來源:互聯網
上載者:User

標籤:

如果您在Activity中定義了一個內部Handler類,如下代碼:

public class MainActivity extends Activity {     private  Handler mHandler = newHandler() {        @Override        public void handleMessage(Message msg) {            //TODO handle message...        }     };     @TargetApi(11)    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mHandler.sendMessageDelayed(Message.obtain(), 60000);         //just finish this activity        finish();    }}

然後運行Android Lint工具會有一個記憶體泄露警告:

This Handler class should be static or leaks might occur (com.example.ta.MainActivity.1)

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

In Android, Handler classes should be static or leaks might occur. Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class.

原因是:

  1. 當Android應用啟動的時候,會先建立一個應用主線程的Looper對象,Looper實現了一個簡單的訊息佇列,一個一個的處理裡面的Message對象。主線程Looper對象在整個應用生命週期中存在。

  2. 當在主線程中初始化Handler時,該Handler和Looper的訊息佇列關聯。發送到訊息佇列的Message會引用發送該訊息的Handler對象,這樣系統可以調用 Handler#handleMessage(Message) 來分發處理該訊息。

  3. 在Java中,非靜態(匿名)內部類會引用外部類對象。而靜態內部類不會引用外部類對象。

  4. 如果外部類是Activity,則會引起Activity泄露 。

當Activity finish後,延時訊息會繼續存在主線程訊息佇列中1分鐘,然後處理訊息。而該訊息引用了Activity的Handler對象,然後這個Handler又引用了這個Activity。這些引用對象會保持到該訊息被處理完,這樣就導致該Activity對象無法被回收,從而導致了上面說的 Activity泄露。

要修改該問題,只需要按照Lint提示的那樣,把Handler類定義為靜態即可,然後通過WeakReference 來保持外部的Activity對象。

private Handler mHandler = new MyHandler(this);private static class MyHandler extends Handler{    private final WeakReference<Activity> mActivity;    public MyHandler(Activity activity) {        mActivity = new WeakReference<Activity>(activity);    }    @Override    public void handleMessage(Message msg) {        System.out.println(msg);        if(mActivity.get() == null) {            return;        }    }}

所以,當你在Activity中使用內部類的時候,需要時刻考慮您是否可以控制該內部類的生命週期,如果不可以,則最好定義為靜態內部類。

        MyHandler ttsHandler = new MyHandler(this); 

        private void test() {                 ttsHandler.sendEmptyMessage(0);         } 

android This Handler class should be static or leaks might occur

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.