溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Handler引起的內(nèi)存泄露怎么解決

發(fā)布時(shí)間:2021-12-24 16:05:12 來(lái)源:億速云 閱讀:137 作者:iii 欄目:移動(dòng)開(kāi)發(fā)

本篇內(nèi)容主要講解“Handler引起的內(nèi)存泄露怎么解決”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Handler引起的內(nèi)存泄露怎么解決”吧!

先看一組簡(jiǎn)單的代碼

public class SampleActivity extends Activity {    private final Handler mHandler = new Handler() {     @Override     public void handleMessage(Message msg) {       // ...      }   } }

當(dāng)我們這樣寫(xiě)在一個(gè)Activity中時(shí),Android Lint會(huì)提示我們這樣一個(gè)  warning: In Android, Handler classes should be static or  leaks might occur.。
意思說(shuō):在Android中,Handler  類(lèi)應(yīng)該是靜態(tài)的否則可能發(fā)生泄漏。

為什么會(huì)是這樣呢?

了解一下Handler

  1. 當(dāng)Android程序***次創(chuàng)建的時(shí)候,在主線程同時(shí)會(huì)創(chuàng)建一個(gè)Looper對(duì)象。Looper實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的消息隊(duì)列,一個(gè)接著一個(gè)處理Message對(duì)象。程序框架所有主要的事件(例如:屏幕上的點(diǎn)擊時(shí)間,Activity生命周期的方法等等)都包含在Message對(duì)象中,然后添加到Looper的消息隊(duì)列中,一個(gè)一個(gè)處理。主線程的Looper存在整個(gè)應(yīng)用程序的生命周期內(nèi)。

  2. 當(dāng)一個(gè)Handler對(duì)象在主線程中創(chuàng)建的時(shí)候,它會(huì)關(guān)聯(lián)到Looper的  message queue  。Message添加到消息隊(duì)列中的時(shí)候Message會(huì)持有當(dāng)前Handler引用,當(dāng)Looper處理到當(dāng)前消息的時(shí)候,會(huì)調(diào)用Handler#handleMessage(Message).

  3. java中,no-static的內(nèi)部類(lèi)會(huì) 隱式的  持有當(dāng)前類(lèi)的一個(gè)引用。static的類(lèi)則沒(méi)有。

在什么地方引起了內(nèi)存的泄露呢?再看看下面一段代碼

public class SampleActivity extends Activity {    private final Handler mHandler = new Handler() {     @Override     public void handleMessage(Message msg) {       // ...     }   }    @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);      // 發(fā)送一個(gè)10分鐘后執(zhí)行的一個(gè)消息     mHandler.postDelayed(new Runnable() {       @Override       public void run() { }     }, 600000);      // 結(jié)束當(dāng)前的Activity     finish();   } }

當(dāng)Activity結(jié)束后,在 Message queue  處理這個(gè)Message之前,它會(huì)持續(xù)存活著。這個(gè)Message持有Handler的引用,而Handler有持有Activity(SampleActivity)的引用,這個(gè)Activity所有的資源,在這個(gè)消息處理之前都不能也不會(huì)被回收,所以發(fā)生了內(nèi)存泄露。

解決辦法,看下面一段代碼

public class SampleActivity extends Activity {    /**    * 使用靜態(tài)的內(nèi)部類(lèi),不會(huì)持有當(dāng)前對(duì)象的引用    */   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);    /**    * 使用靜態(tài)的內(nèi)部類(lèi),不會(huì)持有當(dāng)前對(duì)象的引用    */   private static final Runnable sRunnable = new Runnable() {       @Override       public void run() { }   };    @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);      //  發(fā)送一個(gè)10分鐘后執(zhí)行的一個(gè)消息     mHandler.postDelayed(sRunnable, 600000);      // 結(jié)束     finish();   } }

到此,相信大家對(duì)“Handler引起的內(nèi)存泄露怎么解決”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI