亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

Android中Handler引起的內存泄露問題解決辦法

2019-11-26 15:18:52
字體:
來源:轉載
供稿:網友

在Android常用編程中,Handler在進行異步操作并處理返回結果時經常被使用。通常我們的代碼會這樣實現。

復制代碼 代碼如下:

public class SampleActivity extends Activity {

  private final Handler mLeakyHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      // ...
    }
  }
}

但是,其實上面的代碼可能導致內存泄露,當你使用Android lint工具的話,會得到這樣的警告

復制代碼 代碼如下:

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的主要工作就是一個一個處理消息隊列中的消息對象。在Android中,所有Android框架的事件(比如Activity的生命周期方法調用和按鈕點擊等)都是放入到消息中,然后加入到Looper要處理的消息隊列中,由Looper負責一條一條地進行處理。主線程中的Looper生命周期和當前應用一樣長。

2.當一個Handler在主線程進行了初始化之后,我們發送一個target為這個Handler的消息到Looper處理的消息隊列時,實際上已經發送的消息已經包含了一個Handler實例的引用,只有這樣Looper在處理到這條消息時才可以調用Handler#handleMessage(Message)完成消息的正確處理。

3.在Java中,非靜態的內部類和匿名內部類都會隱式地持有其外部類的引用。靜態的內部類不會持有外部類的引用。關于這一內容可以查看細話Java:”失效”的private修飾符

確實上面的代碼示例有點難以察覺內存泄露,那么下面的例子就非常明顯了

復制代碼 代碼如下:

public class SampleActivity extends Activity {

  private final Handler mLeakyHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      // ...
    }
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Post a message and delay its execution for 10 minutes.
    mLeakyHandler.postDelayed(new Runnable() {
      @Override
      public void run() { /* ... */ }
    }, 1000 * 60 * 10);

    // Go back to the previous Activity.
    finish();
  }
}

分析一下上面的代碼,當我們執行了Activity的finish方法,被延遲的消息會在被處理之前存在于主線程消息隊列中10分鐘,而這個消息中又包含了Handler的引用,而Handler是一個匿名內部類的實例,其持有外面的SampleActivity的引用,所以這導致了SampleActivity無法回收,進行導致SampleActivity持有的很多資源都無法回收,這就是我們常說的內存泄露。

注意上面的new Runnable這里也是匿名內部類實現的,同樣也會持有SampleActivity的引用,也會阻止SampleActivity被回收。

要解決這種問題,思路就是不適用非靜態內部類,繼承Handler時,要么是放在單獨的類文件中,要么就是使用靜態內部類。因為靜態的內部類不會持有外部類的引用,所以不會導致外部類實例的內存泄露。當你需要在靜態內部類中調用外部的Activity時,我們可以使用弱引用來處理。另外關于同樣也需要將Runnable設置為靜態的成員屬性。注意:一個靜態的匿名內部類實例不會持有外部類的引用。 修改后不會導致內存泄露的代碼如下:

復制代碼 代碼如下:

public class SampleActivity extends Activity {

  /**
   * Instances of static inner classes do not hold an implicit
   * reference to their outer class.
   */
  private static class MyHandler extends Handler {
    private final WeakReference<SampleActivity> mActivity;

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

    @Override
    public void handleMessage(Message msg) {
      SampleActivity activity = mActivity.get();
      if (activity != null) {
        // ...
      }
    }
  }

  private final MyHandler mHandler = new MyHandler(this);

  /**
   * Instances of anonymous classes do not hold an implicit
   * reference to their outer class when they are "static".
   */
  private static final Runnable sRunnable = new Runnable() {
      @Override
      public void run() { /* ... */ }
  };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Post a message and delay its execution for 10 minutes.
    mHandler.postDelayed(sRunnable, 1000 * 60 * 10);

    // Go back to the previous Activity.
    finish();
  }
}

其實在Android中很多的內存泄露都是由于在Activity中使用了非靜態內部類導致的,就像本文提到的一樣,所以當我們使用時要非靜態內部類時要格外注意,如果其實例的持有對象的生命周期大于其外部類對象,那么就有可能導致內存泄露。個人傾向于使用文章的靜態類和弱引用的方法解決這種問題。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国产成人av| 久久激情视频久久| 欧美黑人性视频| 91产国在线观看动作片喷水| 国产福利精品av综合导导航| 疯狂欧美牲乱大交777| 亚洲另类欧美自拍| 国产成人精品一区二区| 在线观看亚洲区| 91亚洲精品一区| 亚洲最新在线视频| 成人精品一区二区三区电影黑人| 国产精品a久久久久久| 黄网站色欧美视频| 国内自拍欧美激情| 欧美激情性做爰免费视频| 欧美日韩国产二区| 亚洲风情亚aⅴ在线发布| 久久国产精品久久久| 日本精品中文字幕| 亚洲aaa激情| 亚洲人成电影网| 视频一区视频二区国产精品| 91国产一区在线| 久久久亚洲国产天美传媒修理工| 精品精品国产国产自在线| 国产91色在线播放| 欧美—级a级欧美特级ar全黄| 亚洲视频在线看| 亚洲肉体裸体xxxx137| 久久久精品亚洲| 亚洲电影免费观看高清完整版在线| 国产精品亚洲综合天堂夜夜| 国产成人精品免费久久久久| 国产偷国产偷亚洲清高网站| 91av在线影院| 欧美日本高清视频| 欧美成人免费全部观看天天性色| 久久免费国产视频| 亚洲最大福利视频| 日韩成人激情在线| 色综合久久88色综合天天看泰| 欧美在线视频免费| 国产精品一区二区三区久久久| 精品国产一区二区三区久久久狼| 国产自摸综合网| 国产精品96久久久久久又黄又硬| 亚洲精品视频网上网址在线观看| 久久99精品久久久久久噜噜| 亚洲尤物视频网| 亚洲精品国产suv| 国产精品视频网址| 国产日韩综合一区二区性色av| 亚洲成人黄色网址| 日韩视频永久免费观看| 日韩精品在线视频美女| 中文字幕亚洲欧美日韩在线不卡| 日韩视频―中文字幕| 亚洲护士老师的毛茸茸最新章节| 这里只有精品视频在线| 国产精欧美一区二区三区| 奇米4444一区二区三区| 青青草精品毛片| 亚洲国产高潮在线观看| 91精品久久久久久久久久久久久| 色综合久久久888| 欧美成人黄色小视频| 亚洲色图狂野欧美| 亚洲国产精品久久久久秋霞不卡| 久久久久免费精品国产| 国产精品亚洲欧美导航| 国内精品模特av私拍在线观看| 色噜噜狠狠色综合网图区| 91久久在线观看| 国产精品99一区| 一区二区三区美女xx视频| 日韩中文字幕国产| 成人av在线亚洲| 91在线精品视频| 国产亚洲aⅴaaaaaa毛片| 亚洲精品色婷婷福利天堂| 精品亚洲男同gayvideo网站| 欧美不卡视频一区发布| 国产色婷婷国产综合在线理论片a| 久久成人一区二区| 姬川优奈aav一区二区| 欧美肥老太性生活视频| 欧美黑人一级爽快片淫片高清| 亚洲人成电影网站色xx| 992tv成人免费影院| 日本不卡免费高清视频| 国产精品一区二区av影院萌芽| 亚洲视频在线免费观看| 91高清在线免费观看| 亚洲人成77777在线观看网| 国产美女扒开尿口久久久| 俺去啦;欧美日韩| 中文字幕亚洲国产| 成人网在线视频| 国产乱人伦真实精品视频| 97精品视频在线| 国产精品电影网站| 一个人看的www久久| 久久99精品久久久久久青青91| 国产97在线|日韩| 精品久久久久久久久久久| 一区二区福利视频| 亚洲韩国欧洲国产日产av| 粉嫩老牛aⅴ一区二区三区| 亚洲欧美999| 精品久久久一区二区| 亚洲精品久久7777777| 午夜精品久久久99热福利| 91欧美视频网站| 日韩欧美第一页| 欧美福利视频在线观看| 亚洲区中文字幕| 日韩成人中文电影| 欧美午夜激情视频| 国产精品美女免费| 97超级碰碰碰久久久| 成人av.网址在线网站| 日韩精品免费在线播放| 日韩精品视频三区| 精品视频在线观看日韩| 欧美日韩美女在线| 欧美国产日韩一区二区在线观看| 国产精品一区二区三区免费视频| 亚洲一区二区三区视频| 国产丝袜一区视频在线观看| 国产精品专区第二| 亚洲xxxx18| 一个色综合导航| 日韩色av导航| 精品久久中文字幕久久av| 91精品视频免费观看| 亚洲天堂影视av| 亚洲第一福利视频| 国产精品视频不卡| 亚洲男人天堂2024| 日韩中文字幕在线视频播放| 国产成人精品一区二区在线| 国产成人精品在线视频| 日韩国产欧美区| 亚洲欧美中文字幕在线一区| 国产精品中文字幕久久久| 97在线日本国产| 久久国产精品免费视频| 久久久久久久亚洲精品| 国产一区二区日韩精品欧美精品| 高潮白浆女日韩av免费看| 久久综合88中文色鬼| 国产精品免费网站| 中文字幕无线精品亚洲乱码一区| 精品国产一区二区三区久久狼5月| 欧美xxxx综合视频| 亚洲成av人影院在线观看| 视频在线观看99| 萌白酱国产一区二区| 日韩在线观看网址| 亚洲国产欧美一区二区三区久久| 伊人久久精品视频| 欧美高清在线视频观看不卡| 中文字幕视频在线免费欧美日韩综合在线看|