最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android垃圾回收機(jī)制解決內(nèi)存泄露問(wèn)題

 更新時(shí)間:2016年02月04日 10:28:21   投稿:lijiao  
這篇文章主要介紹了Android垃圾回收機(jī)制解決內(nèi)存泄露問(wèn)題的相關(guān)資料,需要的朋友可以參考下

在android編碼中,會(huì)有一些簡(jiǎn)便的寫(xiě)法和編碼習(xí)慣,會(huì)導(dǎo)致我們的代碼有很多內(nèi)存泄露的問(wèn)題,在這里做一個(gè)已知錯(cuò)誤的總結(jié):
1、編寫(xiě)單例的時(shí)候常出現(xiàn)的錯(cuò)誤。

錯(cuò)誤方式:

 public class Foo{

   private static Foo foo;

   private Context mContext;

   private Foo(Context mContext){

    this.mContext = mContext;

   }

   // 普通單例,非線程安全

   public static Foo getInstance(Context mContext){

    if(foo == null)

     foo = new Foo(mContext);

    return foo;

   }

   public void otherAction(){

    mContext.xxxx();

    ….

   }

  }

錯(cuò)誤原因:

     如果我們?cè)贏ctivity A中或者其他地方使用Foo.getInstance()時(shí),我們總是會(huì)順手寫(xiě)一個(gè)『this』或者『mContext』(這個(gè)變量也是指向this)。試想一下,當(dāng)前我們所用的Foo是單例,意味著被初始化后會(huì)一直存在與內(nèi)存中,以方便我們以后調(diào)用的時(shí)候不會(huì)在此次創(chuàng)建Foo對(duì)象。但Foo中的『mContext』變量一直都會(huì)持有Activity A中的『Context』,導(dǎo)致Activity A即使執(zhí)行了onDestroy方法,也不能夠?qū)⒆约轰N(xiāo)毀。但『applicationContext』就不同了,它一直伴隨著我們應(yīng)用存在(中途也可能會(huì)被銷(xiāo)毀,但也會(huì)自動(dòng)reCreate),所以就不用擔(dān)心Foo中的『mContext』會(huì)持有某Activity的引用,讓其無(wú)法銷(xiāo)毀。

正確方式:   

 public class Foo{

   private static Foo foo;

   private Context mContext;

   private Foo(Context mContext){

    this.mContext = mContext;

   }

   // 普通單例,非線程安全

   public static Foo getInstance(Context mContext){

    if(foo == null)

     foo = new Foo(mContext.getApplicationContext());

    return foo;

   }

   public void otherAction(){

    mContext.xxxx();

    ….

   }

  }

  

2、使用匿名內(nèi)部類的時(shí)候經(jīng)常出現(xiàn)的錯(cuò)誤

錯(cuò)誤方式:

 public class FooActivity extends Activity{

   private TextView textView;   



   private Handler handler = new Handler(){

    @override

    public void handlerMessage(Message msg){

     

    }

   };

   @override

   public void onCreate(Bundle bundle){

    super.onCreate(bundle);

    setContextView(R.layout.activity_foo_layout);

    

    textView = (TextView)findViewById(R.id.textView);

    

    handler.postDelayed(new Runnable(){

     @override

     public void run(){

       textView.setText(“ok”);

     };

    },1000 * 60 * 10);

   }

  }



錯(cuò)誤原因:

     當(dāng)我們執(zhí)行了FooActivity的finish方法,被延遲的消息會(huì)在被處理之前存在于主線程消息隊(duì)列中10分鐘,而這個(gè)消息中又包含了Handler的引用,而Handler是一個(gè)匿名內(nèi)部類的實(shí)例,其持有外面的FooActivity的引用,所以這導(dǎo)致了FooActivity無(wú)法回收,進(jìn)而導(dǎo)致FooActivity持有的很多資源都無(wú)法回收,所以產(chǎn)生了內(nèi)存泄露。

     注意上面的new Runnable這里也是匿名內(nèi)部類實(shí)現(xiàn)的,同樣也會(huì)持有FooActivity的引用,也會(huì)阻止FooActivity被回收。

     一個(gè)靜態(tài)的匿名內(nèi)部類實(shí)例不會(huì)持有外部類的引用。

正確方式:    

 public class FooActivity extends Activity{

   private TextView textView;

   

   private static class MyHandler extends Handler {

   private final WeakReference<FooActivity> mActivity;

   public MyHandler(FooActivity activity) {

    mActivity = new WeakReference<FooActivity>(activity);

   }

   @Override

   public void handleMessage(Message msg) {

    FooActivity activity = mActivity.get();

     if (activity != null) {

       // ...

     }

    }

   }

   private final MyHandler handler = new MyHandler(this);



   @override

   public void onCreate(Bundle bundle){

    super.onCreate(bundle);

    setContextView(R.layout.activity_foo_layout);

    

    textView = (TextView)findViewById(R.id.textView);

    

    handler.postDelayed(new MyRunnable(textView),1000 * 60 * 10);

   }



   private static class MyRunnable implements Runnable{

    private WeakReference<TextView> textViewWeakReference;

    

    public MyRunnable(TextView textView){

     textViewWeakReference = new WeakReference<TextView>(textView);

    }

     @override

     public void run(){

       final TextView textView = textViewWeakReference.get();

       if(textView != null){

        textView.setText("OK");

       }

     };

   }

  }

  

3、在使用handler后,記得在onDestroy里面handler.removeCallbacksAndMessages(object token);

 handler.removeCallbacksAndMessages(null);

  // removeCallbacksAndMessages,當(dāng)參數(shù)為null的時(shí)候,可以清除掉所有跟次handler相關(guān)的Runnable和Message,我們?cè)趏nDestroy中調(diào)用次方法也就不會(huì)發(fā)生內(nèi)存泄漏了。

開(kāi)發(fā)中需要注意的點(diǎn)以免內(nèi)存泄漏:

  •      1.不要讓生命周期長(zhǎng)于Activity的對(duì)象持有到Activity的引用
  •      2.盡量使用Application的Context而不是Activity的Context
  •      3.盡量不要在Activity中使用非靜態(tài)內(nèi)部類,因?yàn)榉庆o態(tài)內(nèi)部類會(huì)隱式持有外部類實(shí)例的引用(具體可以查看細(xì)話Java:”失效”的private修飾符了解)。如果使用靜態(tài)內(nèi)部類,將外部實(shí)例引用作為弱引用持有。
  •      4.垃圾回收不能解決內(nèi)存泄露,了解Android中垃圾回收機(jī)制

獲取context的方法,以及使用上context和applicationContext的區(qū)別:

  •      1.View.getContext,返回當(dāng)前View對(duì)象的Context對(duì)象,通常是當(dāng)前正在展示的Activity對(duì)象。
  •      2.Activity.getApplicationContext,獲取當(dāng)前Activity所在的(應(yīng)用)進(jìn)程的Context對(duì)象,通常我們使用Context對(duì)象時(shí),要優(yōu)先考慮這個(gè)全局的進(jìn)程Context。
  •      3,ContextWrapper.getBaseContext():用來(lái)獲取一個(gè)ContextWrapper進(jìn)行裝飾之前的Context,可以使用這個(gè)方法,這個(gè)方法在實(shí)際開(kāi)發(fā)中使用并不多,也不建議使用。
  •      4.Activity.this 返回當(dāng)前的Activity實(shí)例,如果是UI控件需要使用Activity作為Context對(duì)象,但是默認(rèn)的Toast實(shí)際上使用ApplicationContext也可以。

 大家注意看到有一些NO上添加了一些數(shù)字,其實(shí)這些從能力上來(lái)說(shuō)是YES,但是為什么說(shuō)是NO呢?下面一個(gè)一個(gè)解釋:

     數(shù)字1:啟動(dòng)Activity在這些類中是可以的,但是需要?jiǎng)?chuàng)建一個(gè)新的task。一般情況不推薦。

     數(shù)字2:在這些類中去layout inflate是合法的,但是會(huì)使用系統(tǒng)默認(rèn)的主題樣式,如果你自定義了某些樣式可能不會(huì)被使用。

     數(shù)字3:在receiver為null時(shí)允許,在4.2或以上的版本中,用于獲取黏性廣播的當(dāng)前值。(可以無(wú)視)

     注:ContentProvider、BroadcastReceiver之所以在上述表格中,是因?yàn)樵谄鋬?nèi)部方法中都有一個(gè)context用于使用。

     好了,這里我們看下表格,重點(diǎn)看Activity和Application,可以看到,和UI相關(guān)的方法基本都不建議或者不可使用Application,并且,前三個(gè)操作基本不可能在Application中出現(xiàn)。實(shí)際上,只要把握住一點(diǎn),凡是跟UI相關(guān)的,都應(yīng)該使用Activity做為Context來(lái)處理;其他的一些操作,Service,Activity,Application等實(shí)例都可以,當(dāng)然了,注意Context引用的持有,防止內(nèi)存泄漏。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • Kotlin操作符重載實(shí)例詳解

    Kotlin操作符重載實(shí)例詳解

    Kotlin允許我們?yōu)樽约旱念愋吞峁╊A(yù)定義的一組操作符的實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于Kotlin操作符重載的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • Android實(shí)現(xiàn)邊錄邊播應(yīng)用

    Android實(shí)現(xiàn)邊錄邊播應(yīng)用

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)邊錄邊播應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • android studio的Handler簡(jiǎn)單實(shí)例代碼

    android studio的Handler簡(jiǎn)單實(shí)例代碼

    今天通過(guò)實(shí)例代碼給大家介紹android studio的Handler簡(jiǎn)單用法,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-10-10
  • 詳解Android Bitmap的常用壓縮方式

    詳解Android Bitmap的常用壓縮方式

    這篇文章主要介紹了詳解Android Bitmap的常用壓縮方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • Android 彩色Toast的實(shí)現(xiàn)代碼

    Android 彩色Toast的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Android 彩色Toast的實(shí)現(xiàn)代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-10-10
  • Android?studio實(shí)現(xiàn)app登錄界面

    Android?studio實(shí)現(xiàn)app登錄界面

    這篇文章主要為大家詳細(xì)介紹了Android?studio實(shí)現(xiàn)app登錄界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 詳解Android中OkHttp3的例子和在子線程更新UI線程的方法

    詳解Android中OkHttp3的例子和在子線程更新UI線程的方法

    本篇文章主要介紹了詳解Android中OkHttp3的例子和在子線程更新UI線程的方法 ,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-05-05
  • 第三方開(kāi)源Android TickPlusDrawable狀態(tài)可以通過(guò)動(dòng)畫(huà)切換的按鈕

    第三方開(kāi)源Android TickPlusDrawable狀態(tài)可以通過(guò)動(dòng)畫(huà)切換的按鈕

    Android tickplusdrawable(TickPlusDrawable)是一個(gè)狀態(tài)可以通過(guò)動(dòng)畫(huà)切換的按鈕,本文給大家分享第三方開(kāi)源Android TickPlusDrawable狀態(tài)可以通過(guò)動(dòng)畫(huà)切換的按鈕,感興趣的朋友一起學(xué)習(xí)吧
    2015-12-12
  • 深入淺析Android JSON解析

    深入淺析Android JSON解析

    android中網(wǎng)絡(luò)數(shù)據(jù)傳輸是經(jīng)常被用到的,通常我們使用xml或者json,而json更加輕量,便捷,我們使用的更多。我自己在項(xiàng)目中使用很多,今天就說(shuō)說(shuō)android中怎么去解析JSON,幫助自己總結(jié)內(nèi)容,同時(shí)幫助別人少走彎路
    2015-12-12
  • Android上傳多張圖片的實(shí)例代碼(RxJava異步分發(fā))

    Android上傳多張圖片的實(shí)例代碼(RxJava異步分發(fā))

    本篇文章主要介紹了Android上傳多張圖片的實(shí)例代碼(RxJava異步分發(fā)),具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08

最新評(píng)論

洱源县| 泽库县| 布尔津县| 尼勒克县| 辛集市| 广丰县| 新津县| 邮箱| 嫩江县| 进贤县| 罗定市| 扎囊县| 威远县| 万源市| 德化县| 五原县| 庄浪县| 宝鸡市| 大方县| 蒙城县| 太湖县| 方山县| 邻水| 巴彦县| 闻喜县| 彩票| 南召县| 金塔县| 保靖县| 常德市| 五原县| 沈丘县| 伊宁县| 泰兴市| 温泉县| 建平县| 安化县| 赤水市| 元氏县| 蓬莱市| 香格里拉县|