不可变位图崩溃错误

86
java.lang.IllegalStateException: Immutable bitmap passed to Canvas constructor
at android.graphics.Canvas.<init>(Canvas.java:127)
at app.test.canvas.StartActivity.applyFrame(StartActivity.java:214)
at app.test.canvas.StartActivity$1.onClick(StartActivity.java:163)
at android.view.View.performClick(View.java:4223)
at android.view.View$PerformClick.run(View.java:17275)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4898)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
at dalvik.system.NativeStart.main(Native Method)

我从开发者控制台得到了这个崩溃错误,但我不理解问题出在哪里。

    BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inScaled = true;
    opt.inPurgeable = true;
    opt.inInputShareable = true;
    Bitmap brightBitmap = BitmapFactory.decodeResource(getResources(), position, opt); 
    brightBitmap = Bitmap.createScaledBitmap(brightBitmap, 550, 550, false);
    chosenFrame = brightBitmap;
    Bitmap workingBitmap = Bitmap.createBitmap(chosenFrame);
    workingBitmap = Bitmap.createBitmap(workingBitmap); 
    Canvas c = new Canvas(workingBitmap);

我觉得这和这个有关系吗?

5个回答

236
你必须将你的workingBitmap转换为可变位图Mutable Bitmap,以便在Canvas上进行绘制。(注意:此方法不能帮助节省内存,它会使用额外的内存)。
Bitmap workingBitmap = Bitmap.createBitmap(chosenFrame);
Bitmap mutableBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(mutableBitmap);

这个答案有助于节省内存。 将不可变位图转换为可变位图


这种方法有助于节省内存。我用最简单的方式编辑了答案,以实现可变位图。 - dimetil
当我使用该方法时,应用程序会崩溃,并且在logcat中显示画布无法使用已回收的位图。 - Yerry Huntry
那我可以使用您的方法,而不需要链接中的答案吗? - Yerry Huntry
2
@dimetil 它怎么不浪费内存?它实际上创建了一个完全相同的新位图,所以在这个位图上使用了两倍的内存... - android developer
这是一个我创建的节省内存的方法: https://dev59.com/B2855IYBdhLWcg3wbjvO#16314940 - android developer
选择的框架是什么? - reza_khalafi

44

BitmapFactory.decodeResource() 返回不可变的位图副本,您无法在其画布上绘制。要获取其画布,您需要获取图像位图的可变副本,可以通过添加一行代码来完成。

opt.inMutable = true;

将这行代码添加到您的代码中,这样应该可以解决崩溃问题。


2
这应该是答案,因为它不会消耗内存,而使用bitmap.copy(...)时会发生这种情况。 - java
在将位图加载到内存之前,检查位图属性并设置它们是必要的。如果内存是一个问题,尤其是当您使用具有大尺寸的位图时,可以使用此答案。 - Thracian

5

除非你不想将不可变位图转换为可变位图,否则你可以通过始终重复使用位图来节省内存。

workingBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(workingBitmap);

但我认为这与通过调用使位图可变相同

workingBitmap.isMutable = true

2
位图内没有名为“isMutable”的变量。 - Amr Ashraf

5

这个也有效,我刚刚测试过了。

final BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
return BitmapFactory.decodeByteArray(resultDecoded, 0, resultDecoded.length,options);

1

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