Cómo corregir "lienzo: intentando utilizar un error de mapa de bits reciclado"?

Estoy creando un RecyclerView para mostrar una cuadrícula de imágenes. Al seleccionar uno de ellos, debe abrir una nueva actividad con una transición.

Estoy usando la biblioteca Glide para cargar las imágenes y la transición se ve horrible porque vuelve a cargar la imagen en la nueva actividad. Así que tuve que guardarlo en caché, y luego usarlo para la transición.

Tengo el código, pero a veces si la imagen no carga, él lanza una lona RuntimeException.

Este es el registro:

 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) 

Este es el código para abrir la otra actividad y guardar la imagen como caché:

 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; } 

¿Qué puedo hacer para solucionar este problema? Gracias por adelantado.

Sospecho que de vez en cuando su bitmap consigue en el estado reciclado apenas antes de que la Canvas consiga una ocasión de dibujarla aquí drawable.draw(canvas); .

Una solución rápida debería ser no llamar a bitmap.recycle(); , Que no es estrictamente necesario para Android> 2.3.3 . Si todavía desea recuperar esta memoria con fuerza, tendrá que encontrar una manera de comprobar cuando el mapa de bits en realidad ya no es necesario (es decir, Canvas tuvo la oportunidad de terminar sus operaciones de dibujo).

Mover bitmap.recycle(); A otro lugar en el código donde este mapa de bits realmente ya no es necesario.

No sé mucho sobre el lienzo (no uso animaciones que a menudo), pero si no encuentra ninguna forma de solucionar esto, puede intentar usar esta biblioteca en su lugar: https://github.com/codepath/android_guides / Wiki / shared-element-activity-transition

  • ¿Cuál es la relación entre el lienzo y la matriz en Android?
  • Android guardar y cargar las diferencias PNG bitmaps
  • Rellenar los datos en un mapa de bits de Android tan pronto como sea posible desde C
  • ¿Cómo hacer que cualquier vista dibuje a la lona?
  • Tratando de dibujar en un mapa de bits cargado por el usuario
  • Dando dibujo / Pintura / Ahorro de múltiples mapas de bits
  • Drawable vs Single reutilizable Bitmap mejor con la memoria?
  • Imagen de Facebook como icono grande La notificación aparece en blanco en diferentes teléfonos?
  • Mostrar imagen grande de la tarjeta SD en Android
  • Obtener información de mapa de bits de mapa de bits almacenado en carpeta dibujable
  • OnPreviewFrame data image to imageView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.