位图内存溢出错误

3
我大约一周前在Android市场上上传了一个新的动态壁纸,并且收到了相当多的java.lang.OutOfMemoryError报告。这个错误发生在那些内存不够的小型手机上,因为无法加载我的1115 x 1000像素的图像作为动态壁纸的背景。我尝试使用inSampleSize进行缩放,但缩放后再将其恢复到正常大小时会出现模糊。请问是否有人可以为我的jpg图像提供解决此问题的示例?

你应该将你的问题标题改为“Live wallpaper中的Bitmap OutOfMemoryError”,因为动态壁纸与普通应用程序不同。 - Lumis
3个回答

2

我认为首先要解决的是Slayton的回复,但你也可以通过使用inPreferredConfig以及低于ARGB_8888的任何配置来节省很多内存。尝试使用RGB_565:

BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inPreferredConfig = Bitmap.Config.RGB_565;
InputStream input = getAssets().open("assets/your-image.jpg");
Bitmap bitmap = BitmapFactory.decodeStream(input, null, bounds);    

1

在过去的几周中,我遇到了同样困难的问题。我可以成功地将1900 x 1200位图加载到我的壁纸中,但更改图像会引发内存不足错误。这是因为当您的壁纸运行时,它会创建一个壁纸引擎,如果您转到其设置,则在许多Android设备上将创建第二个预览引擎,因此您的应用程序将占用两倍的内存!

这与加载新图像时垃圾收集器(GC)缓慢有关,将创建内存不足错误。

我找到的解决方案是,在启动第二个预览时停止并卸载第一个引擎中的所有图像,使用:

bitmap.recyle();
bitmap = null;
System.gc();
try {
  synchronized (this){
     wait(200);
  }
} catch (InterruptedException e) {

}

您需要创建一个布尔偏好来通知第一个引擎先停止动画,以便引擎1在onSharedPreferenceChanged中检测到它并停止其doDraw循环,然后清理其图像。在引擎类的onCreate中,您可以检测是否为预览模式:

boolean isPreview = this.isPreview();

我不确定wait(200)是否真的有帮助,但理论上它应该给系统更多时间来执行GC...无论如何,我成功地摆脱了OutOfMemoryError,即使是对于非常容易出现此类错误的Sony xPeria。

此外,您必须避免在动画循环中创建位图,这是绝对不行的。相反,在引擎创建时创建并重复使用切片位图。


0
哪些手机具有1115 x 1000像素的显示密度?正确的做法是将壁纸缩小到手机显示屏的确切尺寸。任何大于此尺寸的都是浪费,因为手机会浪费内存。

它是为480x800屏幕尺寸设计的,但由于背景旋转和移动,因此它更大,否则我可以将其制作得更小。 - Gatekeeper
那么您可以考虑仅在内存中保留所需的壁纸部分。此外,Big Momo的建议也很好。 - slayton
BitmapFactory.Options bfOptions = new BitmapFactory.Options(); bfOptions.inDither = false; bfOptions.inPurgeable = true; bfOptions.inInputShareable = true; bfOptions.inTempStorage = new byte[64 * 1024]; bfOptions.inPreferredConfig = Bitmap.Config.RGB_565;bmp = BitmapFactory.decodeResource(getResources(), R.drawable.space4t22, bfOptions); - Gatekeeper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接