5

Nella mia app sto usando un listview e un listadapter. Quando si fa clic su un determinato elemento secondario in listview, è disponibile una vista testo cliccabile che carica più bitmap in una vista a scorrimento e questa visualizzazione a scorrimento viene visualizzata in un messaggio di avviso.nonostante l'utilizzo di weakreference

Tutto ciò avviene in una classe che estende BaseExpandableListAdapter e quando viene fatto clic su questo collegamento di testo, viene chiamata una classe interna statica che è responsabile del caricamento di tutte queste (9) bitmap. Questa classe interna estende asynctask.

Prima che questi bitmap vengano caricati nella vista a scorrimento, vengono chiamati due metodi statici di questa classe interna che ridimensionano i bitamp a una dimensione adatta allo schermo. Qui uso Bitmapfactory.decoderesource e Bitmap.scaledownBitmap.

Tutto questo funziona FINE, .. MA il programma soffre di una perdita di memoria. Questa perdita era piuttosto grande prima perché questa classe interiore era non statica. Quindi la perdita è stata ridotta rendendo statica questa classe interna. Sì - ridotto, ma non eliminato.

Ho anche reso debole riferimento a diversi oggetti ma senza successo. Ad esempio: ho fatto un riferimento debole dell'oggetto che si riferisce alla classe interiore. Ho fatto un debole riferimento al contesto che è passato alla classe superiore. Ho persino reso w debole riferimento delle bitmap. Nessun successo.

L'heap del Samsung Galaxy S3 è di 64 MB. Quando viene caricato per la prima volta l'elenco con tutti i suoi elementi secondari, l'heap utilizzato è di circa 17 MB. Quindi, quando vengono caricati 9 bitmap, salta a circa 42 MB. Se poi faccio clic su un altro elemento secondario con le immagini utilizzate, l'heap è lo stesso, ma dopo continuare a fare clic e caricare bitmap, l'heap salta improvvisamente a 47 MB ​​... quindi lo stesso scenario ... rimane fermo per un po '- quindi fino a 52 MB .... 56 MB. Quindi devo cliccare e caricare bitmap praticamente per uscire dalla memoria. Diciamo 15 - 20 minuti di uso intensivo.

conclusione: Rendere la statica di classe interna mi ha aiutato a ridurre la perdita di memoria. Tuttavia, nonostante il fatto di avere riferimenti deboli di diversi oggetti (specialmente il contesto), non sono stato in grado di ridurre ulteriormente le perdite.

Qualche suggerimento?

Il codice sotto è un po 'confuso ....

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(); 
      } 
    } 

}

+2

Usa MAT per determinare dove la vostra perdita si sta verificando. – CommonsWare

risposta

2

si stanno mantenendo duplice riferimento ai tuoi bitmap una volta debole e una volta copia cartacea il codice problema è:

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

non si è sbarazzarsi del contenuto del bm

e si sta facendo più di una volta

 scaledBitmap[i] = Bitmap.createScaledBitmap(bm, reqW[i], reqH[i], true); 

        bm.recycle(); 
        bm = null; 

       } 
       System.gc(); 
    WeakReference <Bitmap[] > sc = new WeakReference <Bitmap[]> (scaledBitmap); 

Si dovrebbe fare questo:

ArrayList<WeakReference<Bitmap>>scaledBitmaps= new ArrayList<WeakReference<Bitmap>>(); 

scaledBitmaps.add(new WeakReference<Bitmap>(Bitmap.createScaledBitmap...)); 

and do not use Bitmap[] array 
Problemi correlati