【发布时间】:2015-11-26 03:14:44
【问题描述】:
我目前正在开发我的第一个 android 应用程序,该应用程序涉及用户能够在其库存中获取武器。武器从drawables随机拼凑在一起(刀柄+刀片+握把..等)。库存是一个带有自定义 ArrayAdapter 的网格视图,用于显示武器图标。
问题是一旦生成了大约 15 个武器,我就会收到 OutOfMemoryException。我的目标是让 Inventory 能够支持数百个项目。从日志中,我能够看到问题出在此处:
Bitmap result = Bitmap.createBitmap(woh300, woh300, Bitmap.Config.ARGB_8888);我把位图做的这么大是因为我让用户能够点击物品栏中的武器图标,这会带来它们的放大图像。
这是它的日志:
java.lang.OutOfMemoryError: Failed to allocate a 1930512 byte allocation with 434524 free bytes and 424KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:726)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:547)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:575)
at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:605)
at com.example.android.justdoit.Weapon.<init>(Weapon.java:31)
at com.example.android.justdoit.UpdateInvTask.onPostExecute(UpdateInvTask.java:48)
at com.example.android.justdoit.UpdateInvTask.onPostExecute(UpdateInvTask.java:17)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
我的武器类:
public class Weapon extends Equipment{
public Weapon(Context context){
//get the array of drawables located in the res/values/weapons.xml
Resources res = context.getResources();
TypedArray handles = res.obtainTypedArray(R.array.handles);
TypedArray hilts = res.obtainTypedArray(R.array.hilts);
TypedArray blades = res.obtainTypedArray(R.array.blades);
TypedArray middles = res.obtainTypedArray(R.array.middles);
TypedArray ends = res.obtainTypedArray(R.array.ends);
//randomize the grip, hilt, blade
Random rand = new Random();
Bitmap handle = BitmapFactory.decodeResource(context.getResources(), handles.getResourceId(rand.nextInt(handles.length()), 0));
Bitmap hilt = BitmapFactory.decodeResource(context.getResources(), hilts.getResourceId(rand.nextInt(hilts.length()), 0));
Bitmap blade = BitmapFactory.decodeResource(context.getResources(), blades.getResourceId(rand.nextInt(blades.length()), 0));
Bitmap end = BitmapFactory.decodeResource(context.getResources(), ends.getResourceId(rand.nextInt(ends.length()), 0));
Bitmap middle = BitmapFactory.decodeResource(context.getResources(), middles.getResourceId(rand.nextInt(middles.length()), 0));
Bitmap[] parts = new Bitmap[5];
parts[0] = handle;
parts[1] = hilt;
parts[2] = blade;
parts[3] = middle;
parts[4] = end;
int woh5 = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, res.getDisplayMetrics()));
int woh25 = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, res.getDisplayMetrics()));
int woh130 = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 130, res.getDisplayMetrics()));
int woh138= Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 138, res.getDisplayMetrics()));
int woh162 = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 162, res.getDisplayMetrics()));
int woh170 = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 170, res.getDisplayMetrics()));
int woh172 = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 172, res.getDisplayMetrics()));
int woh258 = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 258, res.getDisplayMetrics()));
int woh300 = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 300, res.getDisplayMetrics()));
Bitmap result = Bitmap.createBitmap(woh300, woh300, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
//rect is left, top, right, bottom
//set the full image. icon is a scaled-down version of the full image
canvas.drawBitmap(parts[2], null, new Rect(woh5 * 25, woh5 * 6, woh5 * 35, woh5 * 37), paint);
canvas.drawBitmap(parts[0], null, new Rect(woh138, woh5 * 37, woh162, woh5 * 52), paint);
canvas.drawBitmap(parts[1], null, new Rect(woh25*3, woh172, woh25*9, woh5 * 42), paint);
canvas.drawBitmap(parts[3], null, new Rect(woh130, woh172, woh170, woh5 * 42), paint);
canvas.drawBitmap(parts[4], null, new Rect(woh138, woh258, woh162, woh5 * 57), paint);
setFullImage(result);
//recycle the typedarrays
result = null;
canvas = null;
handles.recycle();
hilts.recycle();
blades.recycle();
middles.recycle();
ends.recycle();
}
}
我一直在阅读 Android 开发人员指南的“管理位图内存”部分,但作为我的第一个应用程序,我知道我的位图创建可能还很遥远,我想如果我需要完全更改在尝试更好地管理内存之前生成位图的方式。谢谢。
【问题讨论】:
-
尝试调整位图大小