public Pixmap newResizedPixmap(String fileName, PixmapFormat format, double Width, double Height) {
// TODO Auto-generated method stub
Config config = null;
if (format == PixmapFormat.RGB565)
config = Config.RGB_565;
else if (format == PixmapFormat.ARGB4444)
config = Config.ARGB_4444;
else
config = Config.ARGB_8888;
Options options = new Options();
options.inPreferredConfig = config;
options.inPurgeable=true;
options.inInputShareable=true;
options.inDither=false;
InputStream in = null;
Bitmap bitmap = null;
try {
//OPEN FILE INTO INPUTSTREAM
in = assets.open(fileName);
//DECODE INPUTSTREAM
bitmap = BitmapFactory.decodeStream(in, null, options);
if (bitmap == null)
throw new RuntimeException("Couldn't load bitmap from asset '"+fileName+"'");
} catch (IOException e) {
throw new RuntimeException("Couldn't load bitmap from asset '"+fileName+"'");
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
if (bitmap.getConfig() == Config.RGB_565)
format = PixmapFormat.RGB565;
else if (bitmap.getConfig() == Config.ARGB_4444)
format = PixmapFormat.ARGB4444;
else
format = PixmapFormat.ARGB8888;
//THIS IS WHERE THE OOM HAPPENS
return new AndroidPixmap(Bitmap.createScaledBitmap(bitmap, (int)(Width+0.5f), (int)(Height+0.5f), true), format);
}
以下是错误的LogCat输出:
05-07 12:57:18.570: E/dalvikvm-heap(636): Out of memory on a 29736016-byte allocation.
05-07 12:57:18.570: I/dalvikvm(636): "Thread-89" prio=5 tid=18 RUNNABLE
05-07 12:57:18.580: I/dalvikvm(636): | group="main" sCount=0 dsCount=0 obj=0x414a3c78 self=0x2a1b1818
05-07 12:57:18.580: I/dalvikvm(636): | sysTid=669 nice=0 sched=0/0 cgrp=apps handle=705796960
05-07 12:57:18.590: I/dalvikvm(636): | schedstat=( 14462294890 67436634083 2735 ) utm=1335 stm=111 core=0
05-07 12:57:18.590: I/dalvikvm(636): at android.graphics.Bitmap.nativeCreate(Native Method)
05-07 12:57:18.590: I/dalvikvm(636): at android.graphics.Bitmap.createBitmap(Bitmap.java:640)
05-07 12:57:18.590: I/dalvikvm(636): at android.graphics.Bitmap.createBitmap(Bitmap.java:586)
05-07 12:57:18.590: I/dalvikvm(636): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:466)
05-07 12:57:18.590: I/dalvikvm(636): at com.NAME.framework.impl.AndroidGraphics.newResizedPixmap(AndroidGraphics.java:136)
05-07 12:57:18.590: I/dalvikvm(636): at com.NAME.GAME.GameScreen.<init>(GameScreen.java:121)
05-07 12:57:18.600: I/dalvikvm(636): at com.NAME.GAME.CategoryScreen.update(CategoryScreen.java:169)
05-07 12:57:18.600: I/dalvikvm(636): at com.NAME.framework.impl.AndroidFastRenderView.run(AndroidFastRenderView.java:34)
05-07 12:57:18.600: I/dalvikvm(636): at java.lang.Thread.run(Thread.java:856)
05-07 12:57:18.620: I/Choreographer(636): Skipped 100 frames! The application may be doing too much work on its main thread.
05-07 12:57:18.670: W/dalvikvm(636): threadid=18: thread exiting with uncaught exception (group=0x40a13300)
05-07 12:57:18.720: E/AndroidRuntime(636): FATAL EXCEPTION: Thread-89
05-07 12:57:18.720: E/AndroidRuntime(636): java.lang.OutOfMemoryError
05-07 12:57:18.720: E/AndroidRuntime(636): at android.graphics.Bitmap.nativeCreate(Native Method)
05-07 12:57:18.720: E/AndroidRuntime(636): at android.graphics.Bitmap.createBitmap(Bitmap.java:640)
05-07 12:57:18.720: E/AndroidRuntime(636): at android.graphics.Bitmap.createBitmap(Bitmap.java:586)
05-07 12:57:18.720: E/AndroidRuntime(636): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:466)
05-07 12:57:18.720: E/AndroidRuntime(636): at com.NAME.framework.impl.AndroidGraphics.newResizedPixmap(AndroidGraphics.java:136)
05-07 12:57:18.720: E/AndroidRuntime(636): at com.NAME.GAME.GameScreen.<init>(GameScreen.java:121)
05-07 12:57:18.720: E/AndroidRuntime(636): at com.NAME.GAME.CategoryScreen.update(CategoryScreen.java:169)
05-07 12:57:18.720: E/AndroidRuntime(636): at com.NAME.framework.impl.AndroidFastRenderView.run(AndroidFastRenderView.java:34)
05-07 12:57:18.720: E/AndroidRuntime(636): at java.lang.Thread.run(Thread.java:856)
05-07 12:57:18.847: D/Activity:(636): Pausing...
这是使用DDMS的内存泄露报告:
问题嫌疑人1:一个由"dalvik.system.PathClassLoader @ 0x41a06f90"加载的"com.NAME.framework.impl.AndroidPixmap"实例占用了12,393,680(54.30%)字节的内存。内存累积在一个由""加载的"byte[]"实例中。
关键词:dalvik.system.PathClassLoader @ 0x41a06f90、com.NAME.framework.impl.AndroidPixmap、byte[]
详情 »
问题嫌疑人2:由""加载的类"android.content.res.Resources"占用了4,133,808(18.11%)字节的内存。内存累积在一个由""加载的"java.lang.Object[]"实例中。
关键词:java.lang.Object[]、android.content.res.Resources
详情 »
问题嫌疑人3:8个由""加载的"android.graphics.Bitmap"实例占用了2,696,680(11.82%)字节的内存。
最大的实例:•android.graphics.Bitmap @ 0x41462ba0 - 1,048,656(4.59%)字节。•android.graphics.Bitmap @ 0x41a08cf0 - 768,064(3.37%)字节。•android.graphics.Bitmap @ 0x41432990 - 635,872(2.79%)字节。
关键词:android.graphics.Bitmap 详情 »
附加信息: 我使用RGB565或ARGB4444作为图像的配置。我希望对于带有渐变的图像使用ARGB8888,但它会占用太多内存。另一件需要注意的事情是我的Assets类,其中包含游戏使用的所有"Pixmap"。从assets加载的位图存储在这些"Pixmap"中,并在不再需要时(即位图)被删除。也许有更好的存储这些对象的方法吗?请告诉我:
public static Pixmap image1;
public static Pixmap image2;
public static Pixmap image3;
public static Pixmap image4;
public static Pixmap image5;
public static Pixmap image6;
public static Pixmap image7;
public static Pixmap image8;
public static Pixmap image9;
public static Pixmap image10;
public static Pixmap image11;
...
请注意,OOM仅会在分辨率高于我的设备(800x480)的设备上发生,这是因为位图被缩放以适应更大的设备。请注意,这些图像正在画布上绘制,因为我正在开发游戏,对OpenGL不太熟悉。
编辑#1:为了确保您知道我的问题是什么 我在以下行中遇到OOM错误:
Bitmap.createScaledBitmap(bitmap, (int)(Width), (int)(Height), true)
我需要帮助!这是我发布这个可恶游戏的最后障碍!
编辑 #2:我尝试过但无效的新方法
我尝试将解码后的位图添加到 LruCache 中再使用它们。我还尝试了一种方法,创建一个位图映射到临时文件中,然后再次加载它。就像这样:
活动
// Get memory class of this device, exceeding this amount will throw an
// OutOfMemory exception.
final int memClass = ((ActivityManager) getSystemService(
Context.ACTIVITY_SERVICE)).getMemoryClass();
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = 1024 * 1024 * memClass / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// The cache size will be measured in kilobytes rather than
// number of items.
return (bitmap.getRowBytes() * bitmap.getHeight()) / 1024;
}
};
加载位图
//Copy the byte to the file
//Assume source bitmap loaded using options.inPreferredConfig = Config.ARGB_8888;
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer map = null;
try {
map = channel.map(MapMode.READ_WRITE, 0, width*height*4);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bitmap.copyPixelsToBuffer(map);
//recycle the source bitmap, this will be no longer used.
bitmap.recycle();
//Create a new bitmap to load the bitmap again.
bitmap = Bitmap.createBitmap(width, height, config);
map.position(0);
//load it back from temporary
bitmap.copyPixelsFromBuffer(map);
//close the temporary file and channel , then delete that also
try {
channel.close();
randomAccessFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
((AndroidGame) activity).addBitmapToMemoryCache(""+fileName, Bitmap.createScaledBitmap(bitmap, (int)(Width), (int)(Height), true));
return new AndroidPixmap(((AndroidGame) activity).getBitmapFromMemCache(""+fileName), format);
编辑#3:如果您不知道...
我正在放大位图,而不是缩小它们,因此在这种情况下,inSampleSize对我没有帮助。我可以说现在已经尝试过inSampleSize,但所有东西都变得非常模糊,我甚至无法看清哪些东西是什么,即使我将其设置为2!
那么,我该怎么做来解决这个问题?如何能够加载大量经过缩放的位图,同时保持其质量而不会导致OOM错误?