Pérdida de memoria a pesar de usar weakreference

En mi aplicación estoy usando un listview y un listadapter. Cuando se hace clic en un cierto subitem de la vista de lista, hay una vista de texto seleccionable que carga varios mapas de bits en una vista de desplazamiento, y esta vista de desplazamiento se muestra en un alerta.

Todo esto ocurre en una clase que extiende BaseExpandableListAdapter y cuando se hace clic en este enlace de texto – se llama a una clase interna estática responsable de cargar todos estos mapas de bits (9). Esta clase interna se extiende asynctask.

Antes de cargar estos mapas de bits en la vista de desplazamiento, se llaman dos métodos estáticos de esta clase interna que reducen los bitamps a un tamaño que se ajuste a la pantalla. Aquí utilizo Bitmapfactory.decoderesource y Bitmap.scaledownBitmap.

Todo esto funciona bien, pero el programa sufre de un memoryleak. Esta filtración fue bastante grande antes porque esta clase interna no era estática. Así que la fuga se redujo haciendo esta clase interna estática. Sí – reducido, pero no eliminado.

También he hecho weakreference de varios objetos pero sin éxito. Por ejemplo – he hecho una referencia débil del objeto que se refiere a la clase interna. He hecho una débil referencia del contexto que se pasa a la clase interna. Incluso he hecho w una referencia débil de los mapas de bits. Ningún éxito en absoluto.

La pila de mi Samsung Galazy s3 es de 64 MB. Cuando el listview con todo su subitem es cargado primero el montón usado es cerca de 17 MB. Entonces, cuando se cargan 9 mapas de bits, se empuja a unos 42 MB. Si a continuación, haga clic en otro subitem con imágenes utilizadas montón es el mismo – pero después de seguir haciendo clic y cargar mapas de bits el montón de repente jumbs a 47 MB ​​… entonces el mismo escenario …. se queda parado por un tiempo – y luego hasta 52 MB …. 56 MB. Así que tengo que hacer clic y cargar mapas de bits casi para salir de la memoria. Digamos 15 – 20 minutos de uso intensivo.

Conclusión : Hacer la clase interna de estática me ayudó a reducir la pérdida de memoria. Pero a pesar de hacer referencias débiles de varios objetos (especialmente el contexto) no he podido reducir el escape más lejos.

¿Alguna sugerencia?

El código de abajo es un poco complicado ….

static class BitmapWorkerTask extends AsyncTask <Integer, Void, Bitmap[]> { private int[] data; private int[] width, height; private int nmbrOfImages; private String[] scrollText; private ImageView mImage; private View view; private LayoutInflater factory; private AlertDialog.Builder alertadd; private Context context; private WeakReference <Context> sc; private WeakReference <ImageView> mImageV; private WeakReference <Bitmap[]> bitmapV; public BitmapWorkerTask(int[] width, int[] height, int nmbrOfImages, String[] scrollText, Context context) { this.width = width; this.height = height; this.nmbrOfImages = nmbrOfImages; this.scrollText = scrollText; this.context = context; mImage = null; view = null; factory = null; alertadd = null; System.gc(); sc = new WeakReference <Context> (context); try { for (int i = 0; i < scaledBitmap.length; i++) { scaledBitmap[i].recycle(); scaledBitmap[i] = null; } } catch (NullPointerException ne) { System.out.println("nullpointerexception ... gick inte recycla bitmapbilder"); } switch (nmbrOfImages) { case 0: data = new int[1]; break; case 1: data = new int[3]; break; case 2: data = new int[5]; break; case 3: data = new int[9]; break; } } @Override protected Bitmap[] doInBackground(Integer ... params) { switch (nmbrOfImages) { case 0: data[0] = params[0]; break; case 1: data[0] = params[0]; data[1] = params[1]; data[2] = params[2]; break; case 2: data[0] = params[0]; data[1] = params[1]; data[2] = params[2]; data[3] = params[3]; data[4] = params[4]; break; case 3: data[0] = params[0]; data[1] = params[1]; data[2] = params[2]; data[3] = params[3]; data[4] = params[4]; data[5] = params[5]; data[6] = params[6]; data[7] = params[7]; data[8] = params[8]; break; } alertadd = new AlertDialog.Builder(sc.get()); factory = LayoutInflater.from(sc.get()); Bitmap[] bm = decodeSampledBitmapFromResource(sc.get().getResources(), data, width, height); bitmapV = new WeakReference <Bitmap[]> (bm); return bitmapV.get(); } protected void onPostExecute(Bitmap[] bitmap) { switch (nmbrOfImages) { case 0: if (view == null) { view = factory.inflate(R.layout.alertviews, null); } mImage = (ImageView) view.findViewById(R.id.extra_img); mImage.setImageBitmap(bitmap[0]); alertadd.setView(view); alertadd.setNeutralButton("Here!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dlg, int sumthin) { } }); alertadd.show(); break; case 1: if (view == null) { view = factory.inflate(R.layout.alertviews2, null); } mImage = (ImageView) view.findViewById(R.id.img1); mImage.setImageBitmap(bitmap[0]); mImage = (ImageView) view.findViewById(R.id.img2); mImage.setImageBitmap(bitmap[1]); mImage = (ImageView) view.findViewById(R.id.img3); mImage.setImageBitmap(bitmap[2]); try { TextView mText2 = (TextView) view.findViewById(R.id.text_img1_scrollview); mText2.setText(scrollText[0]); mText2 = (TextView) view.findViewById(R.id.text_img2_scrollview); mText2.setText(scrollText[1]); mText2 = (TextView) view.findViewById(R.id.text_img3_scrollview); mText2.setText(scrollText[2]); } catch (NullPointerException ne) { System.out.println("nullpointerexception ... TextView i metoden onPostExecute"); } alertadd.setView(view); alertadd.setNeutralButton("Here!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dlg, int sumthin) { } }); alertadd.show(); break; case 2: if (view == null) { view = factory.inflate(R.layout.alertviews3, null); } mImage = (ImageView) view.findViewById(R.id.img1); mImage.setImageBitmap(bitmap[0]); mImage = (ImageView) view.findViewById(R.id.img2); mImage.setImageBitmap(bitmap[1]); mImage = (ImageView) view.findViewById(R.id.img3); mImage.setImageBitmap(bitmap[2]); mImage = (ImageView) view.findViewById(R.id.img4); mImage.setImageBitmap(bitmap[3]); mImage = (ImageView) view.findViewById(R.id.img5); mImage.setImageBitmap(bitmap[4]); try { TextView mText3 = (TextView) view.findViewById(R.id.text_img1_scrollview); mText3.setText(scrollText[0]); mText3 = (TextView) view.findViewById(R.id.text_img2_scrollview); mText3.setText(scrollText[1]); mText3 = (TextView) view.findViewById(R.id.text_img3_scrollview); mText3.setText(scrollText[2]); mText3 = (TextView) view.findViewById(R.id.text_img4_scrollview); mText3.setText(scrollText[3]); mText3 = (TextView) view.findViewById(R.id.text_img5_scrollview); mText3.setText(scrollText[4]); } catch (NullPointerException ne) { System.out.println("nullpointerexception ... TextView i metoden onPostExecute"); } alertadd.setView(view); alertadd.setNeutralButton("Here!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dlg, int sumthin) { } }); alertadd.show(); break; case 3: if (view == null) { view = factory.inflate(R.layout.alertviews4, null); } AlertDialog.Builder alertadd = new AlertDialog.Builder(context); mImage = (ImageView) view.findViewById(R.id.img1); mImage.setImageBitmap(bitmap[0]); mImage = (ImageView) view.findViewById(R.id.img2); mImage.setImageBitmap(bitmap[1]); mImage = (ImageView) view.findViewById(R.id.img3); mImage.setImageBitmap(bitmap[2]); mImage = (ImageView) view.findViewById(R.id.img4); mImage.setImageBitmap(bitmap[3]); mImage = (ImageView) view.findViewById(R.id.img5); mImage.setImageBitmap(bitmap[4]); mImage = (ImageView) view.findViewById(R.id.img6); mImage.setImageBitmap(bitmap[5]); mImage = (ImageView) view.findViewById(R.id.img7); mImage.setImageBitmap(bitmap[6]); mImage = (ImageView) view.findViewById(R.id.img8); mImage.setImageBitmap(bitmap[7]); mImage = (ImageView) view.findViewById(R.id.img9); mImage.setImageBitmap(bitmap[8]); try { TextView mText4 = (TextView) view.findViewById(R.id.text_img1_scrollview); mText4.setText(scrollText[0]); mText4 = (TextView) view.findViewById(R.id.text_img2_scrollview); mText4.setText(scrollText[1]); mText4 = (TextView) view.findViewById(R.id.text_img3_scrollview); mText4.setText(scrollText[2]); mText4 = (TextView) view.findViewById(R.id.text_img4_scrollview); mText4.setText(scrollText[3]); mText4 = (TextView) view.findViewById(R.id.text_img5_scrollview); mText4.setText(scrollText[4]); mText4 = (TextView) view.findViewById(R.id.text_img6_scrollview); mText4.setText(scrollText[5]); mText4 = (TextView) view.findViewById(R.id.text_img7_scrollview); mText4.setText(scrollText[6]); mText4 = (TextView) view.findViewById(R.id.text_img8_scrollview); mText4.setText(scrollText[7]); mText4 = (TextView) view.findViewById(R.id.text_img9_scrollview); mText4.setText(scrollText[8]); } catch (NullPointerException ne) { System.out.println("nullpointerexception ... TextView i metoden onPostExecute"); } alertadd.setView(view); alertadd.setNeutralButton("Here!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dlg, int sumthin) { } }); alertadd.show(); break; } } /** * * @param options * @param reqW * @param reqH * @return */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqW, int reqH) { int imageHeight = options.outHeight; int imageWidth = options.outWidth; int inSampleSize = 1; if (imageHeight > reqH || imageWidth > reqW) { int heightRatio = Math.round((float) imageHeight / (float) reqH); int widthRatio = Math.round((float) imageWidth / (float) reqW); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; System.out.println("i if-satsen!"); System.out.println("height-ratio: " + heightRatio + "\nwidth-ratio: " + widthRatio); } System.out.println("samplesize: " + inSampleSize); inSampleSize = inSampleSize; return inSampleSize; } @SuppressLint("NewApi") /** * * @param res * @param resId * @param reqW * @param reqH * @return */ public static Bitmap[] decodeSampledBitmapFromResource(Resources res, int[] resId, int[] reqW, int[] reqH) { scaledBitmap = new Bitmap[resId.length]; BitmapFactory.Options options; for (int i = 0; i < resId.length; i++) { options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; Bitmap bm =BitmapFactory.decodeResource(res, resId[i], options); System.out.println("ursprunglig bild: h = " + options.outHeight + " w = " + options.outWidth); options.inSampleSize = calculateInSampleSize(options, reqW[i], reqH[i]); while (options.outHeight < reqH[i] || options.outWidth < reqW[i]) { options.inSampleSize--; System.out.println("räknar nu ner insampleseize\ninSamleSize =" + options.inSampleSize); } options.inJustDecodeBounds = false; bm = BitmapFactory.decodeResource(res, resId[i], options); System.out.println("innan omskalning: h = " + options.outHeight + " w = " + options.outWidth); System.out.println("antalet bytes: " + bm.getByteCount()); System.out.println("native free size: " + Debug.getNativeHeapFreeSize() ); scaledBitmap[i] = Bitmap.createScaledBitmap(bm, reqW[i], reqH[i], true); bm.recycle(); bm = null; } System.gc(); WeakReference <Bitmap[] > sc = new WeakReference <Bitmap[]> (scaledBitmap); return sc.get(); } } 

}

Usted está manteniendo doble referencia a sus mapas de bits una vez débil y una vez copia de su código de problema es:

  Bitmap[] bm = decodeSampledBitmapFromResource(sc.get().getResources(), data, width, height); bitmapV = new WeakReference <Bitmap[]> (bm); 

Usted no está deshaciéndose del contenido de bm

Y lo estás haciendo más de una vez

  scaledBitmap[i] = Bitmap.createScaledBitmap(bm, reqW[i], reqH[i], true); bm.recycle(); bm = null; } System.gc(); WeakReference <Bitmap[] > sc = new WeakReference <Bitmap[]> (scaledBitmap); 

Usted debe hacer esto:

 ArrayList<WeakReference<Bitmap>>scaledBitmaps= new ArrayList<WeakReference<Bitmap>>(); scaledBitmaps.add(new WeakReference<Bitmap>(Bitmap.createScaledBitmap...)); and do not use Bitmap[] array 
  • ¿Cuál es la cantidad máxima de RAM que una aplicación puede usar?
  • ¿Cómo puedo crear Libgdx.so desde el origen para Android con el rastreo gdb habilitado?
  • Público o privado, realmente importa con las variables de Android
  • Android: pérdida de memoria debido a AsyncTask
  • ¿Por qué tengo fugas de memoria cuando estoy haciendo simpy setContentView (R.layout.somelayout)?
  • Excepción de objetos muertos de Android
  • Fuga de memoria a través de IClipboardDataPasteEventImpl
  • Fuga de memoria durante el uso de anuncios intersticiales de Admob
  • ByteBuffer no libera memoria
  • Problemas de memoria - fragmentos
  • Cómo calcular programaticamente todo el tamaño de caché de la aplicación instalada?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.