Android的位图ImageView的内存泄漏(Android bitmap imageview

2019-07-04 09:15发布

我把4×4的ImageView到活动(BoardActivity),并且用户可以通过点击他们改变图像。 随着HTC Desire的(安卓2.2.2),我在大约30分钟的密集使用率-edit了OOM(内存不足):这个活动- 16日开始 ,但不允许其他设备产生这样(的Android 2.1和Android 2.2.1 )。 是否有可能,我做了一些错误与位图/ ImageView的使用率,并导致这个错误? 首先,我加载所有资源ID到地图:

private Map<String, Integer> imageResourceMap;
imageResourceMap = new HashMap<String, Integer>();
        imageResourceMap.put("a", R.drawable.a);
        imageResourceMap.put("b", R.drawable.b);
        imageResourceMap.put("c", R.drawable.c);
//... I store 55 drawable's resourceId in this map

于是我调整并保存每幅图像为位图,在地图表示:

private static Map<String, Bitmap> imageBitmap;

    private void loadBitmaps(int imagesSize) {

    for (String s : imageResourceMap.keySet()) {
        Bitmap tmp = getBitmapFromRes(imageResourceMap.get(s), imagesSize);
        imageBitmap.put(s, tmp);
    }
}

private Bitmap getBitmapFromRes(int resId, int imageSize) {
    Bitmap b = null;
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

        InputStream fis = getResources().openRawResource(resId);
        BitmapFactory.decodeStream(fis, null, o);
        fis.close();

        int scale = 1;
        if (o.outHeight > imageSize || o.outWidth > imageSize) {
            scale = (int) Math.pow(2, (int) Math.round(Math.log(imageSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        fis = getResources().openRawResource(resId);
        b = BitmapFactory.decodeStream(fis, null, o2);
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return b;
}

我一直在数组中imageViews,并初始化使用此功能的所有图片:

private static ImageView[][] imageViews;

private ImageView getImage(String name) {
        MyImageView item = new MyImageView(this, i, j, c + "");
        item.setImageBitmap(imageBitmap.get(name));
        item.setAdjustViewBounds(true);
        return item;
    }

当我需要改变的图像,我简单的改变它的资源:

imageViews[i][j].setImageBitmap(imageBitmap.get("a"));

而之前,我完成的活动,我回收位图:

private void recycleImageBitmaps() {
    for (Bitmap b : imageBitmap.values()) {
        if (b != null) {
            b.recycle();
        }
    }

}

在AndroidManifest.xml我宣布本次活动“singleTask”:

<activity android:name=".game.board.BoardActivity" android:launchMode="singleTask">
    </activity>

在这个应用(游戏),我们重新打开此活动几次......我是怎么了? 可这会导致内存不足的错误?

修正来修正这样的getBitmapFromRes:

private Bitmap getBitmapFromRes(int resId, int imageSize) {
    Bitmap tmp = null;
    Bitmap b = null;
    try {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

        InputStream fis = getResources().openRawResource(resId);
        tmp = BitmapFactory.decodeStream(fis, null, o);
        fis.close();

        int scale = 1;
        if (o.outHeight > imageSize || o.outWidth > imageSize) {
            scale = (int) Math.pow(2, (int) Math.round(Math.log(imageSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        fis = getResources().openRawResource(resId);
        b = BitmapFactory.decodeStream(fis, null, o2);
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }finally{
        if(tmp != null){
            tmp.recycle();
            tmp = null;
        }
    }
    return b;
}

HTC仍然坠毁这项活动的第11个开始。

编辑:从活性(MenuActivity),其具有4的ImageButton,并且是在一个Tabhost活动该活动(BoardActivity)发射。 该imageButtons声明看起来是这样的:

<ImageButton
    android:id="@+id/game_menu_CreateButton"
    android:layout_width="120dip" 
    android:layout_height="120dip"
    android:layout_alignRight="@+id/textView1"
    android:layout_alignTop="@+id/textView1"
    android:background="@drawable/create" 
    android:layout_marginRight="1sp"
    android:layout_marginTop="10sp"
     />

当我开始从MenuActivity的BoardActivity,我不叫finish()在MenuActivity,当我调用finish()在BoardActivity,我不开始新的意图,所以它只是返回到已经打开的MenuActivity。 而16轮的这一点,我得到了OOM。

Answer 1:

为了减少内存,你可以尝试这些东西:

  • 转换成可绘制位图后,您可以设置imageResourceMap为null。 这将卸载3绘项目。
  • 避免存储到所述imageViews的参考。 你可能会存储imageViews它们从用户界面中删除后,即使
  • 回收的位图更​​频繁。 而不是仅仅的onDestroy的,只要你知道,没有使用一个位图,就可以回收。

编辑:基于所述意见交谈:通过BitmapFactory.decodeStream返回的位图(FIS,NULL,O)不被分配给任何变量,因此不循环。 Android的2.2和2.3将在此行中泄漏。



文章来源: Android bitmap imageview memory leak