valida studio ruta renderizado recursos problemas muestra especificada errores error diseño con comunes aparece android bitmap out-of-memory bitmapfactory setbackground

ruta - problemas de renderizado en android studio



Cómo solucionar problemas de java.lang.OutOfMemoryError en Android (4)

Aunque tengo una imagen de tamaño muy pequeño en la carpeta dibujable, recibo este error de los usuarios. Y no estoy usando ninguna función de mapa de bits en el código. Al menos intencionalmente :)

java.lang.OutOfMemoryError at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:683) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:513) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:889) at android.content.res.Resources.loadDrawable(Resources.java:3436) at android.content.res.Resources.getDrawable(Resources.java:1909) at android.view.View.setBackgroundResource(View.java:16251) at com.autkusoytas.bilbakalim.SoruEkrani.cevapSecimi(SoruEkrani.java:666) at com.autkusoytas.bilbakalim.SoruEkrani$9$1.run(SoruEkrani.java:862) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:146) at android.app.ActivityThread.main(ActivityThread.java:5602) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099) at dalvik.system.NativeStart.main(Native Method)

De acuerdo con este stackTrace estoy obteniendo este error en esta línea (''tv'' es un textView):

tv.setBackgroundResource(R.drawable.yanlis);

¿Cuál es el problema? Si necesita alguna otra información sobre el código, puedo agregarlo. ¡Gracias!


Algunos consejos para manejar dicho error / excepción para las aplicaciones de Android:

  1. Actividades y aplicaciones tienen métodos como:

    • onLowMemory
    • onTrimMemory Maneje estos métodos para ver el uso de la memoria.
  2. la etiqueta en Manifiesto puede tener el atributo ''largeHeap'' establecido en TRUE, que solicita más almacenamiento dinámico para la zona de pruebas de la aplicación.

  3. Gestión del almacenamiento en memoria caché y el almacenamiento en memoria caché en memoria:

    • Las imágenes y otros datos podrían haberse almacenado en memoria caché mientras se ejecutaba la aplicación (localmente en actividades / fragmentos y globalmente); debe ser administrado o eliminado.
  4. Uso de la creación de instancias WeakReference, SoftReference de Java, específicamente para archivos.

  5. Si hay tantas imágenes, use una biblioteca / estructura de datos adecuada que pueda administrar la memoria, use el muestreo de imágenes cargadas, maneje el almacenamiento en caché de disco.

  6. Manejar excepción OutOfMemory

  7. Siga las mejores prácticas para la codificación

    • Fugas de memoria (No mantenga todo con referencia fuerte)
  8. Minimice la pila de actividades, por ejemplo, el número de actividades en la pila (No mantenga todo en contexto / actividad)

    • El contexto tiene sentido, esos datos / instancias que no se requieren fuera del alcance (actividad y fragmentos), los mantienen en el contexto apropiado en lugar de la referencia global.
  9. Minimice el uso de estática, muchos más singletons.

  10. Cuide los fundametales de memoria básica del sistema operativo

    • Problemas de fragmentación de la memoria
  11. Involucre GC.Collect () manualmente algunas veces cuando esté seguro de que no es necesario el almacenamiento en memoria caché en memoria.


Debe implementar un administrador de caché LRU al tratar con mapa de bits

http://developer.android.com/reference/android/util/LruCache.html http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html Cuándo debería reciclar un mapa de bits usando LRUCache?

O

Use una biblioteca de niveles como Universal Image Loader:

https://github.com/nostra13/Android-Universal-Image-Loader

EDITAR:

Ahora, cuando trato con imágenes y la mayoría de las veces con mapa de bits, uso Glide, que te permite configurar un Módulo Glide y un LRUCache

https://github.com/bumptech/glide


No puede aumentar el tamaño del almacenamiento dinámico pero puede solicitar el uso de más.

android: largeHeap = "verdadero"

en el manifest.xml , puede agregar en su manifiesto estas líneas para algunas situaciones.

<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:supportsRtl="true" android:theme="@style/AppTheme">

Si los procesos de su aplicación se deben crear con un gran montón de Dalvik. Esto se aplica a todos los procesos creados para la aplicación. Solo se aplica a la primera aplicación cargada en un proceso; si está usando una identificación de usuario compartida para permitir que varias aplicaciones utilicen un proceso, todas deben usar esta opción de manera consistente o tendrán resultados imprevisibles. La mayoría de las aplicaciones no deberían necesitar esto y deberían enfocarse en reducir el uso general de memoria para un mejor rendimiento. Habilitar esto tampoco garantiza un aumento fijo en la memoria disponible, porque algunos dispositivos están limitados por su memoria total disponible.

Para consultar el tamaño de memoria disponible en tiempo de ejecución, use los métodos getMemoryClass() o getLargeMemoryClass() .

Si todavía enfrenta un problema, esto también debería funcionar

BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 8; mBitmapInsurance = BitmapFactory.decodeFile(mCurrentPhotoPath,options);

Si se establece en un valor> 1, solicita al decodificador que muestre por debajo la imagen original y devuelva una imagen más pequeña para guardar la memoria.

Este es el uso óptimo de BitmapFactory.Options.inSampleSize con respecto a la velocidad de visualización de la imagen. La documentación menciona el uso de valores que son una potencia de 2, entonces estoy trabajando con 2, 4, 8, 16, etc.

Permite profundizar en el muestreo de imágenes:

Por ejemplo, no vale la pena cargar una imagen de 1024x768 píxeles en la memoria si eventualmente se mostrará en una miniatura de 128x128 píxeles en un ImageView .

Para indicarle al decodificador que muestre una submuestra de la imagen, que cargue una versión más pequeña en la memoria, configure en inSampleSize en true en su objeto BitmapFactory.Options . Por ejemplo, una imagen con una resolución de 2100 x 1500 píxeles que se decodifica con un inSampleSize de 4 produce un mapa de bits de aproximadamente 512x384. Cargar esto en la memoria utiliza 0.75MB en lugar de 12MB para la imagen completa (suponiendo una configuración de mapa de bits de ARGB_8888 ). Aquí hay un método para calcular un valor de tamaño de muestra que es una potencia de dos basada en el ancho y la altura del objetivo:

public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; }

Nota : Se calcula una potencia de dos valores porque el decodificador usa un valor final al redondear a la potencia más cercana a dos, según la documentación de inSampleSize .

Para usar este método, primero decodifique con inJustDecodeBounds establecido en true , pase las opciones a través y luego descodifique de nuevo usando el nuevo valor de inJustDecodeBounds y en inJustDecodeBounds establecido en false :

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }

Este método facilita la carga de un mapa de bits de tamaño arbitrariamente grande en un ImageView que muestra una miniatura de 100x100 píxeles, como se muestra en el siguiente código de ejemplo:

mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

Puede seguir un proceso similar para decodificar mapas de bits de otras fuentes, sustituyendo el método apropiado BitmapFactory.decode* según sea necesario.

Encontré este código también interesante:

private Bitmap getBitmap(String path) { Uri uri = getImageUri(path); InputStream in = null; try { final int IMAGE_MAX_SIZE = 1200000; // 1.2MP in = mContentResolver.openInputStream(uri); // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, o); in.close(); int scale = 1; while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) { scale++; } Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight); Bitmap bitmap = null; in = mContentResolver.openInputStream(uri); if (scale > 1) { scale--; // scale to max possible inSampleSize that still yields an image // larger than target o = new BitmapFactory.Options(); o.inSampleSize = scale; bitmap = BitmapFactory.decodeStream(in, null, o); // resize to desired dimensions int height = bitmap.getHeight(); int width = bitmap.getWidth(); Log.d(TAG, "1th scale operation dimenions - width: " + width + ", height: " + height); double y = Math.sqrt(IMAGE_MAX_SIZE / (((double) width) / height)); double x = (y / height) * width; Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) x, (int) y, true); bitmap.recycle(); bitmap = scaledBitmap; System.gc(); } else { bitmap = BitmapFactory.decodeStream(in); } in.close(); Log.d(TAG, "bitmap size - width: " +bitmap.getWidth() + ", height: " + bitmap.getHeight()); return bitmap; } catch (IOException e) { Log.e(TAG, e.getMessage(),e); return null; }

Cómo administrar la memoria de su aplicación: link

No es una buena idea usar android:largeHeap="true" aquí está el extracto de google que lo explica,

Sin embargo, la posibilidad de solicitar un montón grande está pensada solo para un pequeño conjunto de aplicaciones que pueden justificar la necesidad de consumir más RAM (como una gran aplicación de edición de fotos). Nunca solicite un gran montón simplemente porque se ha quedado sin memoria y necesita una solución rápida; debe usarlo solo cuando sepa exactamente dónde se está asignando toda su memoria y por qué debe conservarse. Sin embargo, incluso cuando está seguro de que su aplicación puede justificar el gran montón, debe evitar solicitarlo en la medida de lo posible. Usar la memoria extra será cada vez más en detrimento de la experiencia general del usuario porque la recolección de basura tomará más tiempo y el rendimiento del sistema puede ser más lento cuando se cambia de tarea o se realizan otras operaciones comunes.

Después de trabajar de forma inexplicable con errores de falta out of memory errors , diría que agregar esto al manifiesto para evitar el problema no es un pecado.

Verificación del comportamiento de la aplicación en Android Runtime (ART)

El tiempo de ejecución de Android (ART) es el tiempo de ejecución predeterminado para dispositivos con Android 5.0 (nivel de API 21) y superior. Este tiempo de ejecución ofrece una serie de características que mejoran el rendimiento y la suavidad de la plataforma y las aplicaciones de Android. Puede encontrar más información sobre las nuevas funciones de ART en Introducción al arte .

Sin embargo, algunas técnicas que funcionan en Dalvik no funcionan en ART. Este documento le permite saber qué cosas debe observar al migrar una aplicación existente para que sea compatible con ART. La mayoría de las aplicaciones deberían funcionar cuando se ejecuta con ART.

Abordar problemas de recolección de basura (GC)

Bajo Dalvik, las aplicaciones a menudo encuentran útil llamar explícitamente a System.gc () para solicitar recolección de basura (GC). Esto debería ser mucho menos necesario con ART, especialmente si está invocando la recolección de basura para evitar ocurrencias GC_FOR_ALLOC-type o para reducir la fragmentación. Puede verificar qué tiempo de ejecución está en uso llamando a System.getProperty ("java.vm.version"). Si ART está en uso, el valor de la propiedad es "2.0.0" o superior.

Además, se está desarrollando un recolector de basura de compactación en el Proyecto de código abierto de Android (AOSP) para mejorar la administración de la memoria. Debido a esto, debe evitar el uso de técnicas que son incompatibles con la compactación de GC (como guardar punteros a datos de instancia de objeto). Esto es particularmente importante para las aplicaciones que hacen uso de Java Native Interface (JNI). Para obtener más información, vea Cómo evitar problemas de JNI.

Previniendo problemas de JNI

La JNI de ART es algo más estricta que la de Dalvik. Es una buena idea utilizar el modo CheckJNI para detectar problemas comunes. Si su aplicación utiliza el código C / C ++, debe revisar el siguiente artículo:

Además, puede usar la memoria nativa ( NDK y JNI ), por lo que en realidad omite la limitación del tamaño del montón.

Aquí hay algunas publicaciones hechas al respecto:

y aquí hay una biblioteca hecha para eso:


Solo veo dos opciones:

  1. Usted tiene pérdidas de memoria en su aplicación.
  2. Los dispositivos no tienen suficiente memoria cuando se ejecuta su aplicación.