【问题标题】:Canvas: trying to use a recycled bitmap crash on configuration change of fragment画布:尝试在片段的配置更改时使用回收的位图崩溃
【发布时间】:2017-05-12 10:26:07
【问题描述】:

我在片段中有一个列表视图。列表视图的每一行都有图像视图,我正在加载位图图像。我将位图设置为图像视图的标记。下次遇到带有非空标签的图像视图时,我正在回收标签中的位图并将图像重新加载到其中。当活动的方向改变时,这会导致崩溃“画布:尝试使用回收的位图 android.graphics.Bitmap”崩溃。我无法弄清楚为什么会这样。请帮忙。

 Bitmap bitmap = (Bitmap) imageView.getTag();
    if (bitmap != null && !bitmap.isRecycled()) {
        bitmap.recycle();
    }
    Ion.with(appContext)
            .load(uri)
            .asBitmap()
            .setCallback(new FutureCallback<Bitmap>() {
                @Override
                public void onCompleted(Exception e, Bitmap result) {
                    if (result != null) {
                        imageView.setImageBitmap(result);
                        imageView.setTag(result);
                    }
                }
            });

堆栈跟踪: java.lang.RuntimeException: Canvas: 试图使用回收的位图 android.graphics.Bitmap@31a3918 在 android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1270) 在 android.graphics.Canvas.drawBitmap(Canvas.java:1404) 在 android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:544) 在 android.widget.ImageView.onDraw(ImageView.java:1228) 在 android.view.View.draw(View.java:16184) 在 android.view.View.updateDisplayListIfDirty(View.java:15180) 在 android.view.View.draw(View.java:15954) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3609) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399) 在 android.view.View.updateDisplayListIfDirty(View.java:15175) 在 android.view.View.draw(View.java:15954) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3609) 在 android.widget.ListView.drawChild(ListView.java:3418) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399) 在 android.widget.AbsListView.dispatchDraw(AbsListView.java:2615) 在 android.widget.ListView.dispatchDraw(ListView.java:3413) 在 android.view.View.draw(View.java:16187) 在 android.widget.AbsListView.draw(AbsListView.java:4166) 在 android.view.View.updateDisplayListIfDirty(View.java:15180) 在 android.view.View.draw(View.java:15954) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3609) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3399) 在 android.view.View.updateDisplayListIfDirty(View.java:15175) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573) 在 android.view.View.updateDisplayListIfDirty(View.java:15140) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573) 在 android.view.View.updateDisplayListIfDirty(View.java:15140) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573) 在 android.view.View.updateDisplayListIfDirty(View.java:15140) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573) 在 android.view.View.updateDisplayListIfDirty(View.java:15140) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573) 在 android.view.View.updateDisplayListIfDirty(View.java:15140) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573) 在 android.view.View.updateDisplayListIfDirty(View.java:15140) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573) 在 android.view.View.updateDisplayListIfDirty(View.java:15140) 在 android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3593) 在 android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3573) 在 android.view.View.updateDisplayListIfDirty(View.java:15140) 在 android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:281) 在 android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:287) 在 android.view.ThreadedRenderer.draw(ThreadedRenderer.java:322) 在 android.view.ViewRootImpl.draw(ViewRootImpl.java:2615) 在 android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2434) 在 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2067) 在 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107) 在 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013) 在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) 在 android.view.Choreographer.doCallbacks(Choreographer.java:670) 在 android.view.Choreographer.doFrame(Choreographer.java:606) 在 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844) 在 android.os.Handler。

【问题讨论】:

  • 你能澄清一下你的问题吗? Ion 将使用 uri 从内部存储器或服务器获取图像并设置为图像视图。我想我不确定崩溃是否与位图回收有关。请在此处粘贴您的完整日志跟踪
  • 加载位图导致 OutOfMemory 崩溃。因此,每当必须将新图像加载到图像视图中时,我想释放位图使用的内存(已分配给图像视图)。但是,当活动的方向从纵向变为横向时,这会导致崩溃。我在问题中添加了堆栈跟踪

标签: android android-fragments android-bitmap android-orientation


【解决方案1】:
    Bitmap bitmap = (Bitmap) imageView.getTag();
        if (bitmap != null && !bitmap.isRecycled()) {
           // bitmap.recycle();

 Ion.with(appContext)
                .load(uri)
                .asBitmap()
                .setCallback(new FutureCallback<Bitmap>() {
                    @Override
                    public void onCompleted(Exception e, Bitmap result) {
                        if (result != null) {
                            imageView.setImageBitmap(result);
                            imageView.setTag(result);
                        }
                    }
                });

        }


Try this. 

【讨论】:

  • URI 中的图像可能已更改。所以,我每次都需要从uri加载。我认为释放上一个位图使用的内存可以帮助我避免 OutOfMemory 崩溃。
猜你喜欢
  • 2011-06-23
  • 2013-07-12
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-04
  • 1970-01-01
相关资源
最近更新 更多