關於Android out of memory解決辦法的總結

最近在做一個安卓項目,由於app裏面加載了大量的GIF而且必須不斷在後臺循環播放,以至於當我做一個異步加載的listview的時候加載圖片稍多點或者跳轉頁面的到顯示大圖的時候就會出現OOM的情況。對於這樣的問題我用了兩個辦法解決。

       1.listview不必再內存中吃入全部圖片,對圖片使用軟引用只有當listview的圖片需要顯示到屏幕上時才需要將圖片加載到內存,對於跑出屏幕顯示範圍的圖片如果使用軟引用可以及時地回收這樣不會造成OOM。

對於軟引用構建緩衝區具體可以參考http://zhangjunhd.blog.51cto.com/113473/53092/,異步加載圖片可以參考

http://blog.csdn.net/cike110120/article/details/8976169

        2.加載圖片的時候不要一味求大求清晰,可以對圖片進行適當的降採樣,再加載進內存,我是試過如果1M以上的圖片如果降採樣10倍加載到內存顯示在小米2手機上基本是看不出什麼變化,這樣可以極大地緩解內存需求。

Options opts = new Options();
opts.inSampleSize=10;
Bitmap data= BitmapFactory.decodeFile(url);

這樣圖片的品質只有原來的十分之一。

        3.對於不用的activity和需要及時地finish,少用阻塞線程。


    4.MemoryLeak

     在Java中內存泄漏是隻,某個(某些)對象已經不在被使用應該被gc所回收,但有一個對象持有這個對象的引用而阻止這個對象被回收。比如我 們通常會這樣創建一個View TextView tv = new TextView(this);這裏的this通常都是Activity。所以這個TextView就持有着這個Activity的引用。下面看張圖 (Google IO 2011 ppt中抄得)通常情況下,當用戶轉動手機的時候,android會重新調用OnCreate()方法生成一個新的Activity,原來的 Activity應該被GC所回收。但如果有個對象比如一個View的作用域超過了這個Activity(比如有一個static對象或者我們把這個 View的引用放到了Application當中),這時候原來的Activity將不能被GC所回收,Activity本身又持有很多對象的引用,所以 整個Activity的內存被泄漏了。

1
2
3
  備註:經常導致內存泄漏核心原因:
   keeping a long-lived reference to a Context.持有一個context的對象,從而gc不能回收。
  情況如下:

  1.一個View的作用域超出了所在的Activity的作用域,比如一個static的View或者把一個View cache到了application當中 etc
理解:內存:注意靜態的數據和緩存中的數據;注意釋放;
  2.某些與View關聯的Drawable的作用域超出了Activity的作用域。
      3.Runnable對象:比如在一個Activity中啓用了一個新線程去執行一個任務,在這期間這個Activity被系統回收了, 但Runnalbe的 任務還沒有執行完畢並持有Activity的引用而泄漏,但這種泄漏一般來泄漏一段時間,只有Runnalbe的線程執行完閉,這個 Activity又可以被正常回收了。

      4.內存類的對象作用域超出Activity的範圍:比如定義了一個內存類來存儲數據,又把這個內存類的對象傳給了其它Activity 或者Service等。因爲內部類的對象會持有當前類的引用,所以也就持有了Context的引用。解決方法是如果不需要當前的引用把內部類寫成static或者,把內部類抽取出來變成一個單獨的類,或者把避免內部對象作用域超出Activity的作用域。out Of Memery Error 在android中每一個程序所分到的內存大小是有限的,如果超過了這個數就會報Out Of Memory Error。 android給程序分配的內存大小與手機硬件有關,以下是一些手機的數據:
G1:16M Droid:24 Nexus One:32M Xoom:48Ms
所以儘量把程序中的一些大的數據cache到本地文件。以免內存使用量超標。
記得數據傳遞完成之後,把存放在application的HashMap中的數據remove掉,以免發生內存的泄漏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章