不可变位图崩溃错误

Posted

技术标签:

【中文标题】不可变位图崩溃错误【英文标题】:Immutable bitmap crash error 【发布时间】:2012-10-18 15:31:16 【问题描述】:
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);

我觉得和这个有关?

【问题讨论】:

【参考方案1】:

您必须将workingBitmap 转换为Mutable Bitmap 才能在Canvas 上绘图。 (注意:这种方法不利于节省内存,会占用额外的内存)

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

这个答案有助于不要浪费内存 Convert immutable bitmap to a mutable bitmap

【讨论】:

此方法有助于节省内存。我用最简单的方法编辑了答案来做可变位图 当我使用该方法时,应用程序崩溃并且在 logcat 中它说画布不能使用回收的位图 所以我用你的方法没有链接中的答案? @dimetil 怎么不浪费内存?它实际上创建了一个完全相同的新位图,因此您在该位图上使用了 2 倍的内存... 这是我创建的一种节省内存的方法:***.com/a/16314940/878126【参考方案2】:

为了最大限度地减少内存使用,您可以查看这篇关于直接从资源中转换/解码可变位图的帖子:

https://***.com/a/16314940/878126

【讨论】:

【参考方案3】:

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

opt.inMutable = true;

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

【讨论】:

这应该是答案,因为它不会像使用 bitmap.copy(...) 那样消耗内存 在将 Bitmap 加载到内存之前,必须检查 Bitmap 属性并设置它们。如果内存是一个问题,请使用此答案,特别是如果您使用的是大尺寸的位图。【参考方案4】:

除非您不想将 IMMUTABLE 位图转换为 MUTABLE 位图,否则您可以通过 始终重用位图

来节省内存
workingBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(workingBitmap);

但是我认为这可能与通过调用使位图可变

workingBitmap.isMutable = true

【讨论】:

位图中没有名为“isMutable”的变量【参考方案5】:

这个也可以,我刚刚测试过。

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

【讨论】:

以上是关于不可变位图崩溃错误的主要内容,如果未能解决你的问题,请参考以下文章

崩溃:发送到不可变对象的变异方法

应用程序崩溃:发送到不可变对象的变异方法

以可变帧大小动态地将精灵表切割成单独的位图

为啥 Android 使用 pinImages 将可变位图的纹理上传到 GPU?

不能对不可变值使用变异 getter:'self' 是不可变错误

在闭包中使用可变参数时编译器崩溃[重复]