Bitmap的常見問題

在Android中對圖片操作一般都會用到Bitmap類,使用的時候出現的一些常見問題:

內存泄漏 或 OOM(主要問題)
圖片格式設置問題:ALPHA_8、ARGB_4444、ARGB_8888、RGB_565
Bitmap的獲取問題

1、內存泄漏 或 OOM

Android中圖片佔用內存的計算方式:圖片的尺寸(長寬)一個像素佔的內存大小
其中一個像素佔的內存大小按不同圖片格式區分:

  • ALPHA_8 (每個像素佔1字節)
  • ARGB_4444(每個像素佔2字節)
  • ARGB_8888(每個像素佔4字節)
  • RGB_565(每個像素佔2字節)

    根據以上的圖片計算方式,Android給每個application分配的內存有限制,如果使用內存大小超過限制,就會造成OOM。
    如果一個圖片的長寬非常大,如1920*1080,按上面計算方式,內存就會超出限制。
    因此,要對圖片進行壓縮。

    1.1圖片壓縮

    圖片壓縮有幾種形式;有尺寸縮放壓縮,質量壓縮,採樣率壓縮,將圖片格式設置成低內存的格式如RGB565

  • 縮放壓縮

  • 質量壓縮

    /**
     * 質量壓縮:在內存中的大小不變
     *
     * @param image
     * @return
     */
    private static Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int quality = 50;
        image.compress(Bitmap.CompressFormat.JPEG, quality, baos);//這裏壓縮quality%,把壓縮後的數據存放到baos中
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());//把壓縮後的數據baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(bais, null, null);//把ByteArrayInputStream數據生成圖片
        return bitmap;
    }
  • 採樣率壓縮

        /**
     * 質量壓縮,不改變內存大小
     * @param context
     * @param imageId
     * @return
     */
    public static Bitmap CompressByOption(Context context, int imageId) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        //採樣率
        options.inSampleSize = 2;
        //主要的是options參數,不同的decodeResource方法只要用上options
        Bitmap bm = BitmapFactory.decodeResource(context.getResources(), imageId, options);
        return bm;
    }
  • 格式壓縮

    /**
    <ul><li>格式壓縮
    *</li>
    <li>@param context</li>
    <li>@param imageId</li>
    <li>@return
    */
    public static Bitmap CompressByChangeType(Context context, int imageId) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    //將圖片格式改爲RGB_565,佔用內存相對較小
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    Bitmap bm = BitmapFactory.decodeResource(context.getResources(), imageId, options);
    return bm;
    }

1.2 及時回收Bitmap

不再需要時調用bitmap.recycle(),就及時置空
```
/**
 * Recycle the userless bitmap
 *
 * @param bitmap
 */
public static void recycleBitmap(Bitmap bitmap) {
    if (bitmap != null) {
        if (!bitmap.isRecycled()) {
            bitmap.recycle();
        }
        bitmap = null;
    }
    System.gc();
}
```

1.3 運用軟引用 SoftReference<>來進行數據的及時回收,或多圖片加載時利用Lrucache進行緩存

```
SoftReference<Bitmap> bitmapSoftReference = new SoftReference<>(bitmap);
        Bitmap softBitmap = bitmapSoftReference.get();
```

…//TODO

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