Canvas:尝试使用回收的位图 android.graphics.Bitmap

发布于 2024-10-04 01:21:43 字数 5012 浏览 2 评论 0原文

11-24 23:19:18.434: ERROR/AndroidRuntime(12660): Uncaught handler: thread main exiting due to uncaught exception
11-24 23:19:18.684: ERROR/AndroidRuntime(12660): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4384c218
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.graphics.Canvas.throwIfRecycled(Canvas.java:955)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.graphics.Canvas.drawBitmap(Canvas.java:1044)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:291)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.ImageView.onDraw(ImageView.java:908)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6283)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1579)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6286)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.AbsListView.dispatchDraw(AbsListView.java:1323)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.ListView.dispatchDraw(ListView.java:2933)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6389)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at         android.widget.AbsListView.draw(AbsListView.java:2142)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1579)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at     android.view.View.draw(View.java:6286)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6286)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at     android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6286)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1928)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewRoot.draw(ViewRoot.java:1454)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1174)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1774)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.os.Looper.loop(Looper.java:123)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.app.ActivityThread.main(ActivityThread.java:4321)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at java.lang.reflect.Method.invokeNative(Native Method)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at java.lang.reflect.Method.invoke(Method.java:521)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at dalvik.system.NativeStart.main(Native Method)

我使用 SoftReference 实现了图像缓存,并使用图像缓存中的位图设置了 ImageView。

我不使用 Bitmap.recycle() 并在将位图设置为 ImageView 之前检查 Bitmap.isRcycled() 。

我不明白为什么画布是用回收的位图绘制的。 这种情况很少发生,但确实发生过。

有什么建议吗? 谢谢!

11-24 23:19:18.434: ERROR/AndroidRuntime(12660): Uncaught handler: thread main exiting due to uncaught exception
11-24 23:19:18.684: ERROR/AndroidRuntime(12660): java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4384c218
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.graphics.Canvas.throwIfRecycled(Canvas.java:955)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.graphics.Canvas.drawBitmap(Canvas.java:1044)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:291)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.ImageView.onDraw(ImageView.java:908)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6283)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1579)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6286)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.AbsListView.dispatchDraw(AbsListView.java:1323)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.ListView.dispatchDraw(ListView.java:2933)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6389)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at         android.widget.AbsListView.draw(AbsListView.java:2142)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1579)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at     android.view.View.draw(View.java:6286)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6286)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewGroup.drawChild(ViewGroup.java:1581)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at     android.view.ViewGroup.dispatchDraw(ViewGroup.java:1311)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.View.draw(View.java:6286)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1928)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewRoot.draw(ViewRoot.java:1454)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1174)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1774)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.os.Looper.loop(Looper.java:123)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at android.app.ActivityThread.main(ActivityThread.java:4321)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at java.lang.reflect.Method.invokeNative(Native Method)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at java.lang.reflect.Method.invoke(Method.java:521)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
11-24 23:19:18.684: ERROR/AndroidRuntime(12660):     at dalvik.system.NativeStart.main(Native Method)

I implemented an image cache with SoftReference and set an ImageView with a Bitmap from the image cache.

I do not use Bitmap.recycle() and check the Bitmap.isRcycled() before setting the bitmap to an ImageView.

I can not figure out why the canvas is drawing with a recycled bitmap.
It happens rarely but it does happened.

Any suggestion?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

谁的年少不轻狂 2024-10-11 01:21:43

如果有人到达这里并且正在努力找出哪个位图被回收(就像我一样),这就是我最终解决此问题的方法:
1)我放置了一个全局 Thread.setDefaultUncaughtExceptionHandler 来转储堆(实际上我已经用它来诊断 OOM 错误)。处理程序内的代码是这样的:

File f = new File(Environment.getExternalStorageDirectory(),"oom-error.hprof");
String path = f.getAbsolutePath();
// force a few GC before dumping stuff
System.gc();
System.gc();    
Debug.dumpHprofData(path);

2) 使用 这篇很棒的文章,您可以学习如何使用 MAT。

3)在MAT内部,我首先通过“Bitmap”正则表达式过滤类,然后查找位图参考id(在OP情况下:“4384c218”)。这将使您很好地了解哪个视图保存了这个回收的位图,您可以开始考虑它的解决方案。
(就我而言,我从公共缓存中回收图像,其中一些是可绘制对象,也用于 XML 布局,并且应该“固定”到缓存直到 OnDestroy)。

If anyone ever gets here and is struggling to figure out which Bitmap is recycled (like I did), here's what I ended up doing to troubleshoot this:
1) I placed a global Thread.setDefaultUncaughtExceptionHandler which dumps the heap (I actually already had it in place to diagnose OOM errors). The code inside the handler is this:

File f = new File(Environment.getExternalStorageDirectory(),"oom-error.hprof");
String path = f.getAbsolutePath();
// force a few GC before dumping stuff
System.gc();
System.gc();    
Debug.dumpHprofData(path);

2) Using this great article, you can learn how to then load up and analyze the hprof dump file using MAT.

3) Inside the MAT, I first filtered classes by "Bitmap" regex, and then looked for the Bitmap reference id (in OP case: "4384c218"). This will give you a pretty good idea which view is holding this recycled bitmap and you can start thinking of the solution for it.
(In my case, I was recycling images from a common cache, some of which were drawables that were also used in XML layouts and should have been "pinned" to the cache until OnDestroy).

余生再见 2024-10-11 01:21:43

当其中一个活动正在回收其位图时,您不应将相同的图像资源用于不同的活动。

如果您遇到这种情况,请更改其中一项活动的图像资源。

You should not use same image resources for different Activities while one of them is recycling its bitmap.

If you have this situation, changed the image resource of one of those Activities.

那支青花 2024-10-11 01:21:43

同样的问题,但现在我已经解决了。当重新加载 png 或其他时尝试这样:

BitmapFactory.decodeStream(getResources().openRawResource(R.drawable.png1));

我必须知道 png1 何时被回收,如果没有,您也可以尝试捕获 RuntimeException 异常。

The same problem, but now I have solved it. Try this way when reload a png or others:

BitmapFactory.decodeStream(getResources().openRawResource(R.drawable.png1));

I must know when the png1 was recycled, if not, you can also try catch the RuntimeException exception.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文