溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

關于Android內存泄漏的種種總結第二彈

發布時間:2020-03-14 12:54:37 來源:網絡 閱讀:177 作者:Android丶VG 欄目:移動開發

銜接上篇:
新年過后獻上關于Android內存泄漏的種種總結
順手留下GitHub鏈接,需要獲取相關面試等內容的可以自己去找
https://github.com/xiangjiana/Android-MS
(VX:mm14525201314)

在Android應用的開發中,為了防止內存溢出,在處理一些占用內存大而且聲明周 期較長的對象時候,可以盡量應用軟引用和弱引用技術。

軟/弱引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用 的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊 列中。利用這個隊列可以得知被回收的軟/弱引用的對象列表,從而為緩沖器清除已 失效的軟/弱引用。

假設我們的應用會用到大量的默認圖片,比如應用中有默認的頭像,默認游戲圖標 等等,這些圖片很多地方會用到。如果每次都去讀取圖片,由于讀取文件需要硬件 操作,速度較慢,會導致性能較低。所以我們考慮將圖片緩存起來,需要的時候直 接從內存中讀取。但是,由于圖片占用內存空間比較大,緩存很多圖片需要很多的 內存,就可能比較容易發生OutOfMemory異常。這時,我們可以考慮使用軟/弱引 用技術來避免這個問題發生。

以下就是高速緩沖器的雛形: 首先定義一個HashMap,保存軟引用對象。

  private Map <String, SoftReference<Bitmap>> imageCache = new Has 
  hMap <String, SoftReference<Bitmap>> ();

再來定義一個方法,保存Bitmap的軟引用到HashMap。
關于Android內存泄漏的種種總結第二彈
使用軟引用以后,在OutOfMemory異常發生之前,這些緩存的圖片資源的內存空間 可以被釋放掉的,從而避免內存達到上限,避免Crash發生。 如果只是想避免OutOfMemory異常的發生,則可以使用軟引用。

如果對于應用的性 能更在意,想盡快回收一些占用內存比較大的對象,則可以使用弱引用。

另外可以根據對象是否經常使用來判斷選擇軟引用還是弱引用。如果該對象可能會 經常使用的,就盡量用軟引用。如果該對象不被使用的可能性更大些,就可以用弱 引用

ok,繼續回到主題。前面所說的,創建一個靜態Handler內部類,然后對 Handler 持有的對象使用弱引用,這樣在回收時也可以回收 Handler 持有的對象,但是這樣 做雖然避免了 Activity 泄漏,不過 Looper 線程的消息隊列中還是可能會有待處理的 消息,所以我們在 Activity 的 Destroy 時或者 Stop 時應該移除消息隊列 MessageQueue中的消息。

下面幾個方法都可以移除 Message:

  public final void removeCallbacks(Runnable r); 
  public final void removeCallbacks(Runnable r, Object token); 
  public final void removeCallbacksAndMessages(Object token); 
  public final void removeMessages(int what); 
  public final void removeMessages(int what, Object object);
  • 盡量避免使用 static 成員變量
    如果成員變量被聲明為 static,那我們都知道其生命周期將與整個app進程生命 周期一樣。

    這會導致一系列問題,如果你的app進程設計上是長駐內存的,那即使app切到 后臺,這部分內存也不會被釋放。按照現在手機app內存管理機制,占內存較 大的后臺進程將優先回收,因為如果此app做過進程互保?;?,那會造成app在 后臺頻繁重啟。當手機安裝了你參與開發的app以后一夜時間手機被消耗空了 電量、流量,你的app不得不被用戶卸載或者靜默。 這里修復的方法是:

不要在類初始時初始化靜態成員??梢钥紤]lazy初始化。 架構設計上要思考是否真 的有必要這樣做,盡量避免。如果架構需要這么設計,那么此對象的生命周期你有 責任管理起來。

  • 避免 override finalize()
    1、finalize 方法被執行的時間不確定,不能依賴與它來釋放緊缺的資源。時間 不確定的原因是:
  • 虛擬機調用GC的時間不確定
  • Finalize daemon線程被調度到的時間不確定

2、finalize 方法只會被執行一次,即使對象被復活,如果已經執行過了 finalize 方法,再次被 GC 時也不會再執行了,原因是:
含有 finalize 方法的 object 是在 new 的時候由虛擬機生成了一個 finalize reference 在來引用到該Object的,而在 finalize 方法執行的時候,該 object 所 對應的 finalize Reference 會被釋放掉,即使在這個時候把該 object 復活(即用 強引用引用住該 object ),再第二次被 GC 的時候由于沒有了 finalize reference 與之對應,所以 finalize 方法不會再執行。

3、含有Finalize方法的object需要至少經過兩輪GC才有可能被釋放。

  • 資源未關閉造成的內存泄漏
    對于使用了BraodcastReceiver,ContentObserver,File,游標 Cursor, Stream,Bitmap等資源的使用,應該在Activity銷毀時及時關閉或者注銷,否 則這些資源將不會被回收,造成內存泄漏。
  • 一些不良代碼造成的內存壓力
    有些代碼并不造成內存泄露,但是它們,或是對沒使用的內存沒進行有效及時 的釋放,或是沒有有效的利用已有的對象而是頻繁的申請新內存。

比如:
構造 Adapter 時,沒有使用緩存的 convertView ,每次都在創建新的 converView。這里推薦使用 ViewHolder。

總結:

  • 對 Activity 等組件的引用應該控制在 Activity 的生命周期之內; 如果不能就考 慮使用 getApplicationContext 或者 getApplication,以避免 Activity 被外部長 生命周期的對象引用而泄露。
  • 盡量不要在靜態變量或者靜態內部類中使用非靜態外部成員變量(包括context ),即使要使用,也要考慮適時把外部成員變量置空;也可以在內部類中使用弱 引用來引用外部類的變量。
  • 對于生命周期比Activity長的內部類對象,并且內部類中使用了外部類的成員變 量,可以這樣做避免內存泄漏:
    • 將內部類改為靜態內部類
    • 靜態內部類中使用弱引用來引用外部類的成員變量
  • Handler 的持有的引用對象最好使用弱引用,資源釋放時也可以清空 Handler 里面的消息。比如在 Activity onStop 或者 onDestroy 的時候,取消掉該 Handler對象的 MessageRunnable.
  • 在 Java 的實現過程中,也要考慮其對象釋放,最好的方法是在不使用某對象 時,顯式地將此對象賦值為 null,比如使用完Bitmap 后先調用 recycle(),再賦 為null,清空對圖片等資源有直接引用或者間接引用的數組(使用 array.clear() ; array = null)等,最好遵循誰創建誰釋放的原則。
  • 正確關閉資源,對于使用了BraodcastReceiver,ContentObserver,File,游 標 Cursor,Stream,Bitmap等資源的使用,應該在Activity銷毀時及時關閉或 者注銷。
  • 保持對對象生命周期的敏感,特別注意單例、靜態對象、全局性集合等的生命 周期。

刪減了一部分,見諒^_^
順手留下GitHub鏈接,需要獲取相關面試等內容的可以自己去找
https://github.com/xiangjiana/Android-MS
(VX:mm14525201314)
關于Android內存泄漏的種種總結第二彈

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女