问题描述
我把4×4 ImageView的一个活动(BoardActivity),并且用户可以通过单击它们改变图像。随着HTC Desire的(安卓2.2.2),我在大约30分钟的密集使用率 - 编辑了OOM(内存不足):本次活动的第16届开始 - ,但不允许其他设备产生这样的(机器人2.1和Android 2.2.1)。是否有可能,我做了一些错误的位图/ ImageView的使用率,并导致此错误?首先,我加载所有资源ID成图:
I put 4x4 imageView to an activity(BoardActivity), and user can change the images by clicking them. With HTC Desire (Android 2.2.2), I got OOM(Out Of Memory) in about 30 minutes of intensive useage - 16th start of this activity-, but no other devices produces this (android 2.1, and android 2.2.1). Is it possible, that I made some mistake with the bitmap/imageview useage and that causes this error?First, I load all resource ID into a map:
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
于是我调整,每一个图像保存为位图,psented在地图重新$ P $:
Then I resize and save every image into bitmap, represented in 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,并初始化使用此功能的所有图片:
I keep the imageViews in an array, and init all images with this function:
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;
}
当我需要改变形象,我简单的修改它的资源:
When I need to change an image, I simple change its resource:
imageViews[i][j].setImageBitmap(imageBitmap.get("a"));
和权利之前,我完成了活动,我回收位图:
And right before I finish the activity, I recycle the bitmap map:
private void recycleImageBitmaps() {
for (Bitmap b : imageBitmap.values()) {
if (b != null) {
b.recycle();
}
}
}
在AndroidManifest.xml中我宣布本次活动singleTask:
In AndroidManifest.xml I declared this activity "singleTask":
<activity android:name=".game.board.BoardActivity" android:launchMode="singleTask">
</activity>
在此应用程序(游戏),我们重新开始这一活动的几次...我是怎么了?可这会导致内存不足的错误?
In this application(game), we reopen this activity a several times...What did I wrong? Can this cause the Out Of Memory error?
修正更正了getBitmapFromRes是这样的:
CORRECTIONCorrected the getBitmapFromRes like this:
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个开始。
HTC still crashed at the 11th start of this activity.
编辑:从活动(MenuActivity)本次活动(BoardActivity)推出,其中有4个ImageButton的,并且是一个Tabhost活动。该imageButtons的声明是这样的:
This activity(BoardActivity) launch from an Activity(MenuActivity), which have 4 imageButton, and is in a Tabhost activity. The imageButtons declarations look like this:
<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,我不叫完成()
在MenuActivity,当我打电话完成()
在BoardActivity,我不开始新的意图,所以它只是返回到已经打开的MenuActivity。而16轮,我得到了OOM。
When I start the BoardActivity from MenuActivity, I don't call finish()
at MenuActivity, and when I call finish()
at the BoardActivity, I don't start a new intent, so it just return to the already opened MenuActivity. And the 16 round of this, I got the OOM.
推荐答案
要减少内存,你可以尝试这些东西:
To reduce memory, you can try out these things :
- 将可绘制成位图后,您可以设置imageResourceMap为null。这将卸载3可绘制。
- 避免存储参考imageViews。你可能会存储imageViews它们是从UI 删除,即使
- 在更多的时候回收的位图。而不是仅仅的onDestroy的,只要你知道,没有使用一个位图,您可以循环再利用。
编辑:基于所述会话中的注释:由BitmapFactory.de codeStream返回的位图(FIS,空,邻)不分配给任何变量,因此是不回收。 Android的2.2和2.3将有泄漏此行。
Edit : based on the conversation in the comments : The bitmap returned by BitmapFactory.decodeStream(fis, null, o) is not assigned to any variable and hence is not recycled. Android 2.2 and 2.3 will have leaks in this line.
这篇关于Android的位图ImageView的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!