Android應用開發中經常會遇到的問題:
1. 解碼Bitmap的時候産生OutOfMemory錯誤
2. 主動回收Bitmap的時候,因為回收時機把握不到位産生的tring to use a recycled bitmap異常
3. ListView,GridView中因為要加載很多Bitmap,因為放在UI線程裡decode導緻主線程頓卡
4. 自己寫圖檔浏覽器時要加載高清大圖,有可能因為記憶體緊張問題連一張圖檔原始大小的Bitmap都解碼不出來
解決問題的思路:
- 單個或少數大圖檔處理(場景:圖檔浏覽器 )
1. 增大縮放系數,用 BitmapFactory.Options
2. 圖檔源檔案進行轉換,一些沒有透明的PNG圖檔完全可以轉化為JPG格式,這樣記憶體至少節省25%。當然在生成JPG的時候,Config選擇RGB565效果更明顯
3. 局部解碼,Android2.3.3開始加入一個BitmapRegionDecoder的類,可以實作局部解碼。當然這個做圖檔浏覽控件需要的計算稍微麻煩,不過好在Github上有人已經做好了,直接拿來主義吧。開源項目的位址:https://github.com/diegocarloslima/ByakuGallery
4. 當然如果你非要支援2.3.3一下的,又要求不失真。那要麼自己研究JPG,PNG的解碼,自己寫算法。當然,現成的算法其實就在AOSP裡面,下載下傳Android系統的源碼,自己編譯,這需要C,C++,JNI等NDK相關的開發知識。最近忙,如果有空的話我會試試,弄好了當然是發上來了。
- ListView或GridView的優化
1.View複用就不多說了。
2.Bitmap的decode放在異步線程裡處理,可以用AsyncTask,也可以自己寫線程。Bitmap被解碼出來後,要監測Bitmap對應位置的View是否可見,如果可見的話重新整理對應的View。關于Bitmap的優化處理,Android官方有不錯的解決方法http://developer.android.com/training/building-graphics.html。
3.時刻監控目前APP虛拟機的記憶體狀況,超出罰值就回收部分不可見的bitmap。例如當已使用記憶體大于最大記憶體的一半 Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()>Runtime.getRuntime().totalMemory()/2
4.人工幹預GC。bitmap.recycle()在你需要及時清除緩存的時候還是很有必要調用的,否則ListView加載很多圖檔時記憶體會很快飙升的。如果不調用很可能虛拟機會抛出OOM的錯誤。是以,建議在ListView,GridView加載大量圖檔的時候,還是要人工調用bitmap.recycle()方法,必要的時候調用System.gc()以加快記憶體的釋放
5.關于tring to use a recycled bitmap問題的解決。如果是在onDestroy()的時候,去把所有的Bitmap回收掉可能會産生這樣的錯誤。我們可以通過延時個1秒2秒的再去回收,當然這對于很多程式員來說是難以接受的,到底延時多少呢。其實,我們可以先設定相關的ImageView的可見性為不可見,然後再回收即可。還有就是重新整理ListView資料的時候,老的資料不用了,對應的BItmap調用了recycle方法,可能會導緻出現這樣的錯誤,解決的辦法是等等再處理這些BItmap,找到合适的時機,比如新的資料已經加載好了,或者記憶體不夠用的時候順便把這部分垃圾回收掉即可