Blog >Lista Soluciones > Evitar java.lang.OutOfMemoryError
Redimensiona Bitmap usando SoftReference <Bitmap> para evitar java.lang.OutOfMemoryError
Hola desarrolladores, hoy voy a poneros una clase, la cual a mi me ha costado bastante sacar y varios quebraderos de cabeza, pero al fin lo conseguí! Esta clase la uso para poner una imagen bmp en un softreference, y este en un layout. El problema principal vino porque al hacerlo a pelo con el bmp acaba dando la excepcion outofmemory ya que mi aplicacion primero capta las medidas de la pantalla del telefono android y despues redimensiona las imagenes en funcion de estas medidas:
codigo error:
Asi que como el gestor de basura en cuanto a las imagenes de android tiene fallos nativos y en definitiva es una basura segun he leido en distintos foros, la mejor opcion para librarnos de esta odiosa excepcion, es cargar las imagenes en referencias,y cuando a Android le haga falta memoria, sera de donde primero tire:
Ahora para hacer otra referencia en el onCreate de nuestra activity y poder usar la referencia creada en esta clase se usa:
AVISO IMPORTANTE: La excepción java.lang.OutOfMemoryError aun usando SoftReference y siendo la imagen muy grande va a seguir apareciendo, mientras que si son imágenes pequeñas, se corrige a la perfección. Espero que haya sido de ayuda el aporte. Salu2!!
Podeis descargar el código fuente de thebestandroide con sólo compartir en facebook,twitter,linkedin o suscribirte a nuestro canal RSS más abajo.
Redimensiona Bitmap usando SoftReference <Bitmap> para evitar java.lang.OutOfMemoryError
Hola desarrolladores, hoy voy a poneros una clase, la cual a mi me ha costado bastante sacar y varios quebraderos de cabeza, pero al fin lo conseguí! Esta clase la uso para poner una imagen bmp en un softreference, y este en un layout. El problema principal vino porque al hacerlo a pelo con el bmp acaba dando la excepcion outofmemory ya que mi aplicacion primero capta las medidas de la pantalla del telefono android y despues redimensiona las imagenes en funcion de estas medidas:
codigo error:
04-23 06:20:21.521: E/AndroidRuntime(1920): FATAL EXCEPTION: main 04-23 06:20:21.521: E/AndroidRuntime(1920): java.lang.OutOfMemoryError 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:503) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:356) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:379) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:409) 04-23 06:20:21.521: E/AndroidRuntime(1920): at com.example.boxingclock.Img.resizeImage(Img.java:23) 04-23 06:20:21.521: E/AndroidRuntime(1920): at com.example.boxingclock.MainActivity.gestionTema2(MainActivity.java:301) 04-23 06:20:21.521: E/AndroidRuntime(1920): at com.example.boxingclock.MainActivity.onCreate(MainActivity.java:177) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.app.Activity.performCreate(Activity.java:5133) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.app.ActivityThread.access$600(ActivityThread.java:141) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.os.Handler.dispatchMessage(Handler.java:99) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.os.Looper.loop(Looper.java:137) 04-23 06:20:21.521: E/AndroidRuntime(1920): at android.app.ActivityThread.main(ActivityThread.java:5103) 04-23 06:20:21.521: E/AndroidRuntime(1920): at java.lang.reflect.Method.invokeNative(Native Method) 04-23 06:20:21.521: E/AndroidRuntime(1920): at java.lang.reflect.Method.invoke(Method.java:525) 04-23 06:20:21.521: E/AndroidRuntime(1920): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 04-23 06:20:21.521: E/AndroidRuntime(1920): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 04-23 06:20:21.521: E/AndroidRuntime(1920): at dalvik.system.NativeStart.main(Native Method)
Asi que como el gestor de basura en cuanto a las imagenes de android tiene fallos nativos y en definitiva es una basura segun he leido en distintos foros, la mejor opcion para librarnos de esta odiosa excepcion, es cargar las imagenes en referencias,y cuando a Android le haga falta memoria, sera de donde primero tire:
import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; public class Img { //Objeto softReference: Cuando Android necesita memoria lo primero static SoftReferenceBitmp; public SoftReference resizeImage(Context ctx, int resId,int reqWidth, int reqHeight) { // PRIMERO PROGRAMAMOS inJustDecodeBounds=true PARA MODIFICAR MEDIDAS final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; //REFERENCIAMOS A LA IMAGEN BitmapFactory.decodeResource(ctx.getResources(),resId); // CALCULAMOS DIMENSIONES options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; //INSERTO IMAGEN EN REFERENCIA Bitmp=new SoftReference (BitmapFactory.decodeResource(ctx.getResources(),resId)); //reciclamos memoria BitmapFactory.decodeResource(ctx.getResources(),resId).recycle(); return Bitmp; } 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) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } }
Ahora para hacer otra referencia en el onCreate de nuestra activity y poder usar la referencia creada en esta clase se usa:
SoftReferenceimg1; Drawable imagenfondo; protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); //QUITO ORIENTACION ORIZONTAL setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //BACKGROUND,EN MI XML PONGO ID AL LAYOUT DONDE QUIERA HACER LA REDIMENSION LinearLayout layout1 =(LinearLayout)findViewById(R.id.fondomoderno); //CAPTURO DIMENSIONES DE LA PANTALLA Display display = getWindowManager().getDefaultDisplay(); //int alto =150; int alto = display.getWidth(); int ancho = display.getHeight(); Img redimension=new Img(); //COJO EL ID DE LA IMAGEN int resourceId = this.getResources().getIdentifier("fondomodernobox", "drawable", this.getPackageName()); //AHORA LA REFERENCIA SOFTREFERENCE QUE ME DA LA CLASE IMG img1=new SoftReference (redimension.resizeImage(this, resourceId, (int)ancho, (int)alto).get()); //PARA PASAR A DRAWABLE if(img1.get()!=null){ imagenfondo=new BitmapDrawable(img1.get()); } layout1.setBackground(imagenfondo); }
AVISO IMPORTANTE: La excepción java.lang.OutOfMemoryError aun usando SoftReference y siendo la imagen muy grande va a seguir apareciendo, mientras que si son imágenes pequeñas, se corrige a la perfección. Espero que haya sido de ayuda el aporte. Salu2!!
Podeis descargar el código fuente de thebestandroide con sólo compartir en facebook,twitter,linkedin o suscribirte a nuestro canal RSS más abajo.