Mostrando entradas con la etiqueta Android softreference bitmap. Mostrar todas las entradas
Mostrando entradas con la etiqueta Android softreference bitmap. Mostrar todas las entradas

Redimension Bitmap con SoftReference evitando OutOfMemoryError

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:
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:
SoftReference img1;
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. 



Compartir Compartir Compartir Compartir