5

私のアプリでは、私はlistviewとlistadapterを使用しています。リストビュー内の特定のサブアイテムをクリックすると、スクロールビューにいくつかのビットマップをロードするクリック可能なテキストビューがあります。このスクロールビューは、警告ダイアログに表示されます。weakreferenceを使用しているにもかかわらずメモリリーク

このすべてはBaseExpandableListAdapterを拡張するクラスで起こると、このテキストリンクをクリックしたときに - 静的内部クラスは、これらすべての(9)ビットマップをロードする責任があることと呼ばれています。この内部クラスはasynctaskを継承します。

これらのビットマップがスクロールビューにロードされる前に、この内部クラスの2つの静的メソッドが呼び出され、ビットマップを画面に合ったサイズにスケールダウンします。ここでは、Bitmapfactory.decoderesourceとBitmap.scaledownBitmapを使用します。

これはすべてFINEですが、プログラムはメモリリークに悩まされています。この内部クラスは静的ではなかったので、このリークはかなり大きかった。だから、この内部クラスを静的にすることによって、リークはであるを減らしました。はい - 削減されますが、削除されません。

私はまた、いくつかのオブジェクトを弱く参照しましたが、成功しませんでした。たとえば、私は内部クラスを参照するオブジェクトの弱い参照を作成しました。私は内部クラスに渡されるコンテキストの弱い参照を作成しました。私もビットマップの弱い参照をwにしました。全く成功していない。

私のSamsung Galazy s3のheapsizeは64 MBです。すべてのサブ項目を含むリストビューが最初にロードされるとき、ヒープは約17 MBです。その後、9ビットマップがロードされると、約42MBになります。ヒープを使用して別のサブアイテムをクリックするとヒープは同じですが、クリックしてビットマップを読み込んだ後、ヒープが突然47 MB​​になります。 MB .... 56 MB。だから、メモリを使い果たすために、ビットマップをクリックして読み込む必要があります。たとえば、15〜20分の集中使用を考えてみましょう。

結論:内部クラスを静的にすると、メモリリークを減らすのに役立ちました。しかし、いくつかのオブジェクト(特に文脈)の弱参照にもかかわらず、私は漏れをさらに減らすことができませんでした。

提案がありますか?

以下のコードは少し厄介です....

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

使用MATを。 – CommonsWare

答えて

2

あなたは一度弱い あなたのビットマップに二重の参照を維持し、あなたの問題のコードがある ハードコピーワンスされています

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

bmの内容を削除していません

、あなたが複数回

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

        bm.recycle(); 
        bm = null; 

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

それをやっているあなたはこれを行う必要があります:あなたのリークが発生している場所を決定するために

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

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

and do not use Bitmap[] array 
関連する問題