Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/232.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java “如何修复”;画布:尝试使用回收的位图错误;?_Java_Android_Canvas_Bitmap_Android Glide - Fatal编程技术网

Java “如何修复”;画布:尝试使用回收的位图错误;?

Java “如何修复”;画布:尝试使用回收的位图错误;?,java,android,canvas,bitmap,android-glide,Java,Android,Canvas,Bitmap,Android Glide,我正在创建一个RecyclerView来显示一个图片网格。选择其中一项时,应打开一个带有转换的新活动 我正在使用Glide library加载图片,过渡看起来很糟糕,因为它会在新活动中重新加载图片。因此,我必须将其保存在缓存中,然后将其用于转换 我有代码,但有时如果图片没有加载,它会抛出画布运行时异常 这是日志: 07-03 15:19:58.633 28461-28461/jahirfiquitiva.project E/AndroidRuntime﹕ FATAL EXCEPTION: ma

我正在创建一个
RecyclerView
来显示一个图片网格。选择其中一项时,应打开一个带有转换的新活动

我正在使用Glide library加载图片,过渡看起来很糟糕,因为它会在新活动中重新加载图片。因此,我必须将其保存在缓存中,然后将其用于转换

我有代码,但有时如果图片没有加载,它会抛出画布运行时异常

这是日志:

07-03 15:19:58.633  28461-28461/jahirfiquitiva.project E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: jahirfiquitiva.project, PID: 28461
    java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@29f09d20
            at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1282)
            at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:599)
            at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:538)
            at android.widget.ImageView.onDraw(ImageView.java:1176)
            at android.view.View.draw(View.java:15239)
            at android.view.View.updateDisplayListIfDirty(View.java:14175)
            at android.view.View.getDisplayList(View.java:14197)
            at android.view.GhostView.onDraw(GhostView.java:52)
            at android.view.View.draw(View.java:15239)
            at android.view.View.updateDisplayListIfDirty(View.java:14175)
            at android.view.View.getDisplayList(View.java:14197)
            at android.view.View.draw(View.java:14967)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3406)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199)
            at android.view.View.updateDisplayListIfDirty(View.java:14170)
            at android.view.View.getDisplayList(View.java:14197)
            at android.view.View.draw(View.java:14967)
            at android.view.ViewGroup.drawChild(ViewGroup.java:3406)
            at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199)
            at android.view.ViewOverlay$OverlayViewGroup.dispatchDraw(ViewOverlay.java:219)
            at android.view.View.draw(View.java:15248)
            at android.widget.FrameLayout.draw(FrameLayout.java:598)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2906)
            at android.view.View.updateDisplayListIfDirty(View.java:14175)
            at android.view.View.getDisplayList(View.java:14197)
            at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:273)
            at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:279)
            at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:318)
            at android.view.ViewRootImpl.draw(ViewRootImpl.java:2536)
            at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2352)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1982)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5891)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
            at android.view.Choreographer.doFrame(Choreographer.java:550)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5289)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
这是打开其他活动并将图片另存为缓存的代码:

private void openViewer(WallpapersAdapter.WallsHolder wallsHolder, int index, final HashMap<String, String> data) {

        final Intent intent = new Intent(wallsActivity, ViewerActivity.class);
        intent.putExtra("wallUrl", data.get(WallpapersActivity.WALL));
        intent.putExtra("wallName", data.get(WallpapersActivity.NAME));
        intent.putExtra("transitionName", ViewCompat.getTransitionName(wallsHolder.wall));

        //save image from drawable
        //get its path and send it to activity
        Bitmap bitmap = drawableToBitmap(wallsHolder.wall.getDrawable());
        //Convert to byte array and send to the other activity

        Log.e("Resolution", bitmap.getWidth() + "x" + bitmap.getHeight());
        try {
            //Write file
            String filename = "bitmap.png";
            FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);

            //Cleanup
            stream.close();
            bitmap.recycle();

            //Pop intent
            intent.putExtra("image", filename);
        } catch (Exception e) {
            e.printStackTrace();
        }

        ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
                this, wallsHolder.wall, ViewCompat.getTransitionName(wallsHolder.wall));
        startActivity(intent, options.toBundle());

    }

    public static Bitmap drawableToBitmap (Drawable drawable) {
        Bitmap bitmap = null;
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            if(bitmapDrawable.getBitmap() != null) {
                return bitmapDrawable.getBitmap();
            }
        }

        if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
            bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
        } else {
            bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }
private void openViewer(wallpasdapter.WallsHolder WallsHolder,int索引,最终HashMap数据){
最终意图=新意图(wallsActivity、ViewerActivity.class);
intent.putExtra(“wallUrl”,data.get(wallparsactivity.WALL));
intent.putExtra(“wallName”,data.get(wallparsactivity.NAME));
intent.putExtra(“transitionName”,viewcompt.getTransitionName(wallsHolder.wall));
//从drawable中保存图像
//获取其路径并将其发送到“活动”
位图位图=drawableToBitmap(wallsHolder.wall.getDrawable());
//转换为字节数组并发送到其他活动
Log.e(“分辨率”,bitmap.getWidth()+“x”+bitmap.getHeight());
试一试{
//写入文件
字符串filename=“bitmap.png”;
FileOutputStream=this.openFileOutput(文件名,Context.MODE\u PRIVATE);
compress(bitmap.CompressFormat.PNG,100,流);
//清理
stream.close();
bitmap.recycle();
//流行意图
intent.putExtra(“图像”,文件名);
}捕获(例外e){
e、 printStackTrace();
}
ActivityOptions Compat options=ActivityOptions Compat.MakeScenetTransitionAnimation(
这个,wallsHolder.wall,ViewCompat.getTransitionName(wallsHolder.wall));
startActivity(intent,options.toBundle());
}
公共静态位图drawableToBitmap(可绘制){
位图=空;
if(BitmapDrawable的可绘制实例){
BitmapDrawable BitmapDrawable=(BitmapDrawable)drawable;
if(bitmapDrawable.getBitmap()!=null){
返回bitmapDrawable.getBitmap();
}
}

if(drawable.getIntrinsicWidth()我对画布了解不多(我不经常使用动画)但是如果你没有找到任何方法来解决这个问题,你可以尝试使用这个库来代替:

我怀疑你的位图偶尔会在
画布
有机会在这里绘制
drawable.draw(Canvas);
之前进入循环状态


快速解决方案应该是不要调用
位图.recycle();
,这不是严格要求的。如果仍要强制回收此内存,则必须找到一种方法来检查位图何时确实不再需要(即,
画布有机会完成其绘图操作)。

移动
位图.recycle();
到代码中确实不再需要此位图的另一个位置。

我通过添加以下内容解决了此问题:

Glide.with(activity).clear(view);
加载图像之前:

Glide.with(activity)
                .load(imageUrl)
                .apply(options)
                .placeholder(R.drawable.loading_image)
                .error(R.drawable.not_found)
                .into(view);
见文件:


使用此自定义ImageView类

public class MyImageView extends ImageView {
 
    public MyImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
 
    public MyImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
 
    public MyImageView(Context context) {
        super(context);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        try {
            super.onDraw(canvas);
        } catch (Exception e) {
            Log.i(MyImageView.class.getSimpleName(), "Catch Canvas: trying to use a recycled bitmap");
        }
    }
 
}

我不确定,但我认为应该将位图保存到真实的对象引用中,而不是缓存中。当不再使用位图时,可以允许缓存释放位图。