我正在使用
Drawable drawable = res.getDrawable(id);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(bitmap);
bitmap.eraseColor(0);
drawable.setBounds(0,0, width, height);
drawable.draw(canvas);
return load(bitmap, linear);
以给定的宽度和高度将资源ID中的drawable加载到OpenGL中。 (使用
android.opengl.GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
) 加载函数执行GL调用,并且还调用bitmap.recycle()。
我自己指定宽度和高度,因为Android会将分辨率与屏幕尺寸匹配,这是我不希望的。
现在我的问题(这部分工作正常): 如果我是第一次从Android Studio启动我的应用程序,则一切正常;但是,如果我想重新启动它,它会因OutOfMemoryError而崩溃。在两种情况下,我都进行完全相同的通话。
我将问题定位在Android的资源管理中,如您在堆分析中所看到的: my most expensive allocations
我的图像的原始大小均小于9 MB(512x512,RGBA,所以1 MB)。 我如何防止Android存储这些大字节数组,这些数组可能意味着某种缓存;但是,在安装应用程序后第一次启动时却无法运行?
我正在Android 6.0.1,API版本23,Galaxy S5上进行测试。
答案 0 :(得分:0)
texImage2D的实现如下所示:
public static void texImage2D(int target, int level, int internalformat,
Bitmap bitmap, int border) {
if (bitmap == null) {
throw new NullPointerException("texImage2D can't be used with a null Bitmap");
}
if (bitmap.isRecycled()) {
throw new IllegalArgumentException("bitmap is recycled");
}
if (native_texImage2D(target, level, internalformat, bitmap, -1, border)!=0) {
throw new IllegalArgumentException("invalid Bitmap format");
}
}
看起来好像没有回收任何东西。您确定没有将巨大的位图加载到内存中吗?即使不仅仅一次,两次调用就足以保证您的应用程序发生巨大的爆炸(我见过它在我的应用程序中发生过很多次)。请记住,重新启动活动并不意味着重新启动过程。
在首次加载之前运行Android Profiler,并检查它占用了多少内存。
此外,您可以自己缓存和重用位图。
答案 1 :(得分:0)
我通过将文件放入资源目录的原始文件夹并使用加载它们来解决了(我自己)
fun loadBitmap(res: Resources, rawId: Int): Bitmap {
val inputStream = BufferedInputStream(res.openRawResource(rawId))
return BitmapFactory.decodeStream(inputStream)
}
然后致电
load(bitmap, linear);
和
bitmap.recycle()
像以前一样。 幸运的是,这些都是png / jpeg文件,因此我不需要drawables文件夹的其他功能。使用此功能,他们将自动使用正确的分辨率。
我的Java RAM分配现在从原来的110 MB恢复到了25 MB至35 MB: