我将4×4 imageView放入活动(BoardActivity),用户可以通过单击更改图像.使用HTC Desire(
Android 2.2.2),我在大约30分钟的密集使用中获得了OOM(Out Of Memory)-EDIT:此活动的第16次开始 – 但是没有其他设备产生这个(android 2.1和android 2.2.1) ).是否有可能,我在bitmap / imageview使用中犯了一些错误并导致此错误?
首先,我将所有资源ID加载到地图中:
首先,我将所有资源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
然后我调整大小并将每个图像保存到位图中,在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,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,o2); fis.close(); } catch (IOException e) { e.printStackTrace(); }finally{ if(tmp != null){ tmp.recycle(); tmp = null; } } return b; }
HTC仍然在此次活动的第11次开始时坠毁.
编辑:
此活动(BoardActivity)从Activity(MenuActivity)启动,它有4个imageButton,并且处于Tabhost活动中. 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时,我没有在MenuActivity上调用finish(),当我在BoardActivity上调用finish()时,我没有开始新的意图,所以它只返回已经打开的MenuActivity.而这16轮,我得到了OOM.
解决方法
为了减少内存,你可以试试这些东西:
>将drawable转换为位图后,可以将imageResourceMap设置为null.这将卸载3个drawables.
>避免存储对imageViews的引用.您可能正在存储imageViews,即使它们已从UI中删除
>更频繁地回收位图.一旦您知道未使用一个位图,您就可以回收它,而不仅仅是onDestroy.
编辑:基于注释中的对话:BitmapFactory.decodeStream(fis,o)返回的位图未分配给任何变量,因此不会被回收. Android 2.2和2.3将在这一行中出现泄漏.