내 응용 프로그램에서 나는 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();
}
}
}
사용 MAT 확인합니다. – CommonsWare