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.
- ¿Cómo dibujo texto en negrita en un mapa de bits?
- La compresión de mapa de bits de Android no es buena
- Convierta la matriz de bytes NV21 en formato legible de mapa de bits
- Inclinar un mapa de bits sólo en la dirección vertical
- PorterduffXfermode: borra una sección de un mapa de bits
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.
- Android, ayuda a girar la imagen en el tacto
- Guardar hardware acelerado android lienzo como mapa de bits
- BitmapFactory.decodeStream (inputStream) devuelve siempre null cuando algunos bytes son incorrectos
- Captura toda la vista de desplazamiento más grande que la pantalla
- ¿Por qué dibujar bitmaps es muy lento en algunos teléfonos Android 2.2?
- Generar una suma md5 desde un objeto Bitmap de Android
- Configuración de varios elementos personalizados en MultiAutoCompleteTextView: Android
- Escritura Bitmap al almacenamiento externo (sdcard)
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
- Biblioteca AppCompat 23.2.1 no funciona con espresso v2.2.2
- Ocultar el teclado al mostrar DialogFragment en la tableta?