亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android內(nèi)存泄漏終極解決篇(下)

 更新時(shí)間:2016年01月12日 10:08:59   作者:Huang_Cai_Yuan  
這篇文章主要為大家介紹了Android內(nèi)存泄漏的相關(guān)資料,哪些寫(xiě)法容易造成內(nèi)存泄漏,該如何解決?感興趣的小伙伴們可以參考一下

一、概述

Android內(nèi)存泄漏終極解決篇(上)中我們介紹了如何檢查一個(gè)App是否存在內(nèi)存泄漏的問(wèn)題,本篇將總結(jié)典型的內(nèi)存泄漏的代碼,并給出對(duì)應(yīng)的解決方案。內(nèi)存泄漏的主要問(wèn)題可以分為以下幾種類型:

  • 靜態(tài)變量引起的內(nèi)存泄漏
  • 非靜態(tài)內(nèi)部類引起的內(nèi)存泄漏
  • 資源未關(guān)閉引起的內(nèi)存泄漏

二、靜態(tài)變量引起的內(nèi)存泄漏

在java中靜態(tài)變量的生命周期是在類加載時(shí)開(kāi)始,類卸載時(shí)結(jié)束。換句話說(shuō),在android中其生命周期是在進(jìn)程啟動(dòng)時(shí)開(kāi)始,進(jìn)程死亡時(shí)結(jié)束。所以在程序的運(yùn)行期間,如果進(jìn)程沒(méi)有被殺死,靜態(tài)變量就會(huì)一直存在,不會(huì)被回收掉。如果靜態(tài)變量強(qiáng)引用了某個(gè)Activity中變量,那么這個(gè)Activity就同樣也不會(huì)被釋放,即便是該Activity執(zhí)行了onDestroy(不要將執(zhí)行onDestroy和被回收劃等號(hào))。這類問(wèn)題的解決方案為:1.尋找與該靜態(tài)變量生命周期差不多的替代對(duì)象。2.若找不到,將強(qiáng)引用方式改成弱引用。比較典型的例子如下:

單例引起的Context內(nèi)存泄漏

public class IMManager {
  private Context context;
  private static IMManager mInstance;

  public static IMManager getInstance(Context context) {
    if (mInstance == null) {
      synchronized (IMManager.class) {
        if (mInstance == null)
          mInstance = new IMManager(context);
      }
    }
    return mInstance;
  }

  private IMManager(Context context) {
    this.context = context;
  }

}

當(dāng)調(diào)用getInstance時(shí),如果傳入的context是Activity的context。只要這個(gè)單例沒(méi)有被釋放,這個(gè)Activity也不會(huì)被釋放。

解決方案
傳入Application的context,因?yàn)锳pplication的context的生命周期比Activity長(zhǎng),可以理解為Application的context與單例的生命周期一樣長(zhǎng),傳入它是最合適的。

public class IMManager {
  private Context context;
  private static IMManager mInstance;

  public static IMManager getInstance(Context context) {
    if (mInstance == null) {
      synchronized (IMManager.class) {
        if (mInstance == null)
          //將傳入的context轉(zhuǎn)換成Application的context
          mInstance = new IMManager(context.getApplicationContext());
      }
    }
    return mInstance;
  }

  private IMManager(Context context) {
    this.context = context;
  }

}

三、非靜態(tài)內(nèi)部類引起的內(nèi)存泄漏

在java中,創(chuàng)建一個(gè)非靜態(tài)的內(nèi)部類實(shí)例,就會(huì)引用它的外圍實(shí)例。如果這個(gè)非靜態(tài)內(nèi)部類實(shí)例做了一些耗時(shí)的操作,就會(huì)造成外圍對(duì)象不會(huì)被回收,從而導(dǎo)致內(nèi)存泄漏。這類問(wèn)題的解決方案為:1.將內(nèi)部類變成靜態(tài)內(nèi)部類 2.如果有強(qiáng)引用Activity中的屬性,則將該屬性的引用方式改為弱引用。3.在業(yè)務(wù)允許的情況下,當(dāng)Activity執(zhí)行onDestory時(shí),結(jié)束這些耗時(shí)任務(wù)。

內(nèi)部線程造成的內(nèi)存泄漏

public class LeakAty extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aty_leak);
    test();
  }

  public void test() {
    //匿名內(nèi)部類會(huì)引用其外圍實(shí)例LeakAty.this,所以會(huì)導(dǎo)致內(nèi)存泄漏
    new Thread(new Runnable() {

      @Override
      public void run() {
        while (true) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }
  }

解決方案
將非靜態(tài)匿名內(nèi)部類修改為靜態(tài)匿名內(nèi)部類

public class LeakAty extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aty_leak);
    test();
  }
  //加上static,變成靜態(tài)匿名內(nèi)部類
  public static void test() {
    new Thread(new Runnable() {

      @Override
      public void run() {
        while (true) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }).start();
  }
}

Handler引起的內(nèi)存泄漏

public class LeakAty extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aty_leak);
    fetchData();

  }

  private Handler mHandler = new Handler() {
    public void handleMessage(android.os.Message msg) {
      switch (msg.what) {
      case 0:
        // 刷新數(shù)據(jù)
        break;
      default:
        break;
      }

    };
  };

  private void fetchData() {
    //獲取數(shù)據(jù)
    mHandler.sendEmptyMessage(0);
  }
}

mHandler 為匿名內(nèi)部類實(shí)例,會(huì)引用外圍對(duì)象LeakAty.this,如果該Handler在Activity退出時(shí)依然還有消息需要處理,那么這個(gè)Activity就不會(huì)被回收。

解決方案

public class LeakAty extends Activity {
  private TextView tvResult;
  private MyHandler handler;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.aty_leak);
    tvResult = (TextView) findViewById(R.id.tvResult);
    handler = new MyHandler(this);
    fetchData();

  }
  //第一步,將Handler改成靜態(tài)內(nèi)部類。
  private static class MyHandler extends Handler {
    //第二步,將需要引用Activity的地方,改成弱引用。
    private WeakReference<LeakAty> atyInstance;
    public MyHandler(LeakAty aty) {
      this.atyInstance = new WeakReference<LeakAty>(aty);
    }

    @Override
    public void handleMessage(Message msg) {
      super.handleMessage(msg);
      LeakAty aty = atyInstance == null ? null : atyInstance.get();
      //如果Activity被釋放回收了,則不處理這些消息
      if (aty == null||aty.isFinishing()) {
        return;
      }
      aty.tvResult.setText("fetch data success");
    }
  }

  private void fetchData() {
    // 獲取數(shù)據(jù)
    handler.sendEmptyMessage(0);
  }

  @Override
  protected void onDestroy() {
    //第三步,在Activity退出的時(shí)候移除回調(diào)
    super.onDestroy();
    handler.removeCallbacksAndMessages(null);
  }
}

四、資源未關(guān)閉引起的內(nèi)存泄漏

當(dāng)使用了BraodcastReceiver、Cursor、Bitmap等資源時(shí),當(dāng)不需要使用時(shí),需要及時(shí)釋放掉,若沒(méi)有釋放,則會(huì)引起內(nèi)存泄漏。

綜上所述,內(nèi)存泄漏的主要情況為上面的三大類型,最終歸結(jié)為一點(diǎn),就是資源在不需要的時(shí)候沒(méi)有被釋放掉。所以在編碼的過(guò)程中要注意這些細(xì)節(jié),提高程序的性能。

相關(guān)文章

  • Android應(yīng)用開(kāi)發(fā)之簡(jiǎn)易、大氣音樂(lè)播放器實(shí)現(xiàn)專輯倒影效果

    Android應(yīng)用開(kāi)發(fā)之簡(jiǎn)易、大氣音樂(lè)播放器實(shí)現(xiàn)專輯倒影效果

    這篇文章主要介紹了Android應(yīng)用開(kāi)發(fā)之簡(jiǎn)單、大氣音樂(lè)播放器實(shí)現(xiàn)專輯倒影效果,對(duì)android音樂(lè)播放器感興趣的朋友可以參考下
    2015-10-10
  • Android webview用法實(shí)例簡(jiǎn)析

    Android webview用法實(shí)例簡(jiǎn)析

    這篇文章主要介紹了Android webview用法,結(jié)合實(shí)例形式簡(jiǎn)單分析了Android中webview的功能、用法與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2016-01-01
  • Android基于OpenCV實(shí)現(xiàn)圖像金字塔

    Android基于OpenCV實(shí)現(xiàn)圖像金字塔

    圖像金字塔是圖像中多尺度表達(dá)的一種,最主要用于圖像的分割,是一種以多分辨率來(lái)解釋圖像的有效但概念簡(jiǎn)單的結(jié)構(gòu)。本文講解Android基于OpenCV實(shí)現(xiàn)圖像金字塔的步驟
    2021-06-06
  • Android隨機(jī)給出加減乘除的四則運(yùn)算算術(shù)題

    Android隨機(jī)給出加減乘除的四則運(yùn)算算術(shù)題

    這篇文章主要為大家詳細(xì)介紹了Android隨機(jī)給出加減乘除的四則運(yùn)算算術(shù)題,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Android Studio中一套代碼多渠道打包的實(shí)現(xiàn)方法

    Android Studio中一套代碼多渠道打包的實(shí)現(xiàn)方法

    這篇文章主要介紹了Android Studio中一套代碼多渠道打包的實(shí)現(xiàn)方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-05-05
  • Android嚴(yán)苛模式StrictMode使用詳解

    Android嚴(yán)苛模式StrictMode使用詳解

    StrictMode類是Android 2.3 (API 9)引入的一個(gè)工具類,可以用來(lái)幫助開(kāi)發(fā)者發(fā)現(xiàn)代碼中的一些不規(guī)范的問(wèn)題,以達(dá)到提升應(yīng)用響應(yīng)能力的目的
    2018-01-01
  • Android中Retrofit庫(kù)的高級(jí)使用與原理

    Android中Retrofit庫(kù)的高級(jí)使用與原理

    在 Android 開(kāi)發(fā)中,網(wǎng)絡(luò)請(qǐng)求是一個(gè)極為關(guān)鍵的部分,Retrofit 作為一個(gè)強(qiáng)大的網(wǎng)絡(luò)請(qǐng)求庫(kù),能夠簡(jiǎn)化開(kāi)發(fā)流程,提供高效的網(wǎng)絡(luò)請(qǐng)求能力,本文將深入介紹 Retrofit 的高級(jí)使用與原理,幫助讀者更全面地理解和應(yīng)用這一庫(kù),需要的朋友可以參考下
    2023-08-08
  • Android底部導(dǎo)航組件BottomNavigationView

    Android底部導(dǎo)航組件BottomNavigationView

    這篇文章主要介紹了Android底部導(dǎo)航組件BottomNavigationView,BottomNavigationView是相當(dāng)于一個(gè)導(dǎo)航的標(biāo)簽,但是它的形式就是像QQ微信之類的界面,至于寫(xiě)出后怎樣綁定這三個(gè)界面,就得用Fragment,寫(xiě)這三個(gè)頁(yè)面的布局
    2023-03-03
  • Android 4.0 設(shè)置全屏修改的解決方法

    Android 4.0 設(shè)置全屏修改的解決方法

    本篇文章是對(duì)Android 4.0 中設(shè)置全屏修改的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • 為Android系統(tǒng)添加config.xml 新配置的設(shè)置

    為Android系統(tǒng)添加config.xml 新配置的設(shè)置

    這篇文章主要介紹了為Android系統(tǒng)添加config.xml 新配置的設(shè)置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-03-03

最新評(píng)論