Bitmap的管理
與圖片有關的軟件免不了要做Bitmap的管理,要不然很可能就會發生OutOfMemory(OOM)的錯誤,致使程序崩潰。引起這種現象的原因無非是:
1.長期保持對某個對象或數據的引用,導致java的垃圾回收器不能回收不再使用的內存空間;
2.正在使用的有效對象占用內存空間大,導致多個有效對象生成時,吃完程序所分配的內存;
一般會報這種錯誤:java.lang.OutOfMemoryError: bitmap size exceeds VM budget,這是因為,android系統中讀取位圖Bitmap時.分給虛擬機中圖片的堆棧大小只有8M。所以不管是如何調用的圖片,太多太大虛擬機肯定會報這個錯誤。(對于實際的機器來說,這個內存分配是不是很大?)
而像相冊這樣子的應用,最好的效果是:
1)將圖片(單個資源)縮小到適當的大小,以便于同時加載多張圖片;
2)就算縮小到適當的大小,我們也不能將所有圖片的引用同時保存在內存中,這時候需要將部分的圖片釋放;
遇到這種問題的解決方案是:縮小圖片+回收資源的方式,來優化內存:
盡量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource來設置一張大圖,因為這些函數在完成decode后,最終都是通過java層的createBitmap來完成的,需要消耗更多內存。因此,改用先通過BitmapFactory.decodeStream方法,創建出一個bitmap,再將其設為ImageView的 source,decodeStream最大的秘密在于其直接調用JNI>>nativeDecodeAsset()來完成decode,無需再使用java層的createBitmap,從而節省了java層的空間。如果在讀取時加上圖片的Config參數,可以更有效減少加載的內存,從而更有效阻止拋out of Memory異常。
另外,decodeStream直接拿的圖片來讀取字節碼了, 不會根據機器的各種分辨率來自動適應,使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相應的圖片資源,否則在不同分辨率機器上都是同樣大小(像素點數量),顯示出來的大小就不對了。
1)縮小圖片的方式:
InputStream is = this.getResources().openRawResource(R.drawable.pic1); BitmapFactory.Options options=new BitmapFactory.Options(); options.inJustDecodeBounds = false; options.inSampleSize = 10; //width,hight設為原來的十分一 Bitmap btp =BitmapFactory.decodeStream(is,null,options);2)回收圖片的方式:
if(!bmp.isRecycle() ){bmp.recycle() //回收圖片所占的內存system.gc() //提醒系統及時回收 }緩存:加載圖片的時候首先檢測是否被緩存然后再去動作
//用來存放圖片的緩存HashMap<Integer, Bitmap> bitmapCache = new HashMap<Integer, Bitmap>();//如果沒有圖片,或者已經存在if(bitmapCache.isEmpty() || !AppConst.bitmapCache.containsKey(position)){bitmapCache.put(position, bm);System.out.println("-----------inset cache---------");}定義FreeBitmap函數,在activity結束的時候,調用FreeBitmap函數,回收map中的資源
private void FreeBitmap(HashMap<Integer, Bitmap> cache){if(cache.isEmpty()){return;}for(Bitmap bitmap:cache.values()){if(bitmap != null && !bitmap.isRecycled()){bitmap.recycle();System.out.println("=============recycle bitmap=======");}}cache.clear();}轉載于:https://blog.51cto.com/cfy10/1325174
總結
- 上一篇: MongoDB实战(4)MapReduc
- 下一篇: Python 继承标准类时发生了什么