5

내 응용 프로그램에서 나는 listview 및 listadapter를 사용하고 있습니다. 목록보기의 특정 하위 항목을 클릭하면 여러 비트 맵을 스크롤 뷰에로드하는 클릭 가능한 텍스트 뷰가 있으며이 스크롤 뷰는 경고 대화 상자에 표시됩니다.weakreference 사용에도 불구하고 메모리 누수가

이 모든 것은 BaseExpandableListAdapter를 확장하는 클래스에서 발생하며이 텍스트 링크를 클릭하면 모든 (9) 비트 맵을로드하는 정적 내부 클래스가 호출됩니다. 이 내부 클래스는 asynctask를 확장합니다.

이러한 비트 맵이 scrollview에로드되기 전에이 내부 클래스의 두 가지 정적 메서드가 호출되어 비트 맵을 화면에 맞는 크기로 축소합니다. 여기서 저는 Bitmapfactory.decoderesource와 Bitmap.scaledownBitmap을 사용합니다.

이 모든 것이 제대로 작동하지만 .. 프로그램은 메모리 누수로 고통 받고 있습니다. 이 내부 클래스가 정적이 아니기 때문에이 누출은 다소 커졌습니다. 누설은이 내부 클래스를 정적으로 만들어으로 줄인 입니다. 예 - 축소되었지만 제거되지 않았습니다.

나는 또한 몇 가지 객체를 약하게 참조했지만 성공하지는 못했습니다. 예를 들어, 내부 클래스를 참조하는 객체에 대한 약한 참조를 만들었습니다. 나는 내부 클래스에 전달 된 컨텍스트의 약한 참조를 만들었습니다. 나는 심지어 비트 맵에 대해 약한 참조를 만들었다. 전혀 성공하지 못했습니다.

내 삼성 Galazy s3의 heapsize는 64MB입니다. 모든 하위 항목이있는 목록보기가 처음로드 될 때 힙은 약 17MB입니다. 그런 다음 9 개의 비트 맵이로드되면 약 42MB 크기로 바뀝니다. 그런 다음 이미지가있는 다른 하위 항목을 클릭하면 힙이 동일합니다. 그러나 비트 맵을 계속 클릭하고로드 한 후 갑자기 힙이 47MB로 늘어납니다 ... 그러면 같은 시나리오가 나타납니다. 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 
관련 문제