다소 큰 비트 맵을로드하고 표시하는 활동이 있습니다. 이미지 뷰에이 비트 맵의 로딩은 AsyncTask를 이루어집니다오리엔테이션 변경 및 가비지 수집에서 안드로이드 메모리 누수가 발생했습니다.
private static Bitmap decodeSampledBitmapFromFile(String filepath, int reqWidth,int orientation) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filepath,options);
if(orientation==0){
options.inSampleSize = calculateInSampleSizeWidth(options, reqWidth);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap d = BitmapFactory.decodeFile(filepath,options);
return Bitmap.createScaledBitmap(d, reqWidth, d.getHeight()*reqWidth/d.getWidth(), true);
}
else{
options.inSampleSize = calculateInSampleSizeHeight(options,reqWidth);
options.inJustDecodeBounds = false;
Bitmap d = BitmapFactory.decodeFile(filepath,options);
return Bitmap.createScaledBitmap(d, d.getWidth()*reqWidth/d.getHeight(), reqWidth, true);
}
}
private static int calculateInSampleSizeWidth(BitmapFactory.Options options, int reqWidth) {
int inSampleSize = 1;
if (options.outWidth > reqWidth) {
final int halfWidth = options.outWidth/2;
while ((halfWidth/inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
은 다음과 같습니다 : 위험한 처음부터 비즈니스, 그러나 우리는 아래의 표준 방법을 사용하여 BitmapFactory를 사용하여로드
private static class LoadBitmapTask extends AsyncTask<String, Void, Bitmap>{
private ViewSampleActivity _activity;
public LoadBitmapTask(ViewSampleActivity activity){
this._activity = activity;
}
public void detach(){
this._activity = null;
}
@Override
protected Bitmap doInBackground(String... params) {
try{
String filename = params[0];
Display display = _activity.getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int orientation = getCameraPhotoOrientation(_activity,Uri.fromFile(new File(filename)),filename);
Bitmap d = null;
d = decodeSampledBitmapFromFile(filename, (int)(((double)size.x)*0.85),orientation);
d = rotateBitmapAppropriately(_activity,Uri.fromFile(new File(filename)),filename,d);
return d;
}
catch(Exception e){
return null;
}
}
@Override
protected void onPostExecute(Bitmap result){
try{
_activity.sampleImageView.setImageBitmap(result);
_activity.sampleImageView.setVisibility(View.VISIBLE);
_activity.sampleImageView.getLayoutParams().height = result.getHeight();
_activity.sampleImageView.getLayoutParams().width = result.getWidth();
_activity.viewSampleLayout.getLayoutParams().height = LayoutParams.WRAP_CONTENT;
_activity.hasPicture = true;
}
catch(Exception e){
e.printStackTrace();
}
}
}
메모리 누수를 피하기 위해 Activity의 onStop 메서드를 오버로드하여 AsyncTask에서 활동을 분리했습니다.
@Override
public void onStop(){
if(this.loadBitmapTask!=null){
loadBitmapTask.detach();
}
super.onStop();
}
이상한 동작은 처음 실행시로드가 정상적으로 작동한다는 것입니다. 오리엔테이션을 변경하면 활동이 올바르게 다시로드됩니다. 그러나 방향이 5 개 정도 변경되면 응용 프로그램이 메모리 부족 오류로 인해 중단됩니다. 비트 맵은 명백한 범인 인 것처럼 보일 것입니다. 나는 어떤 ui 요소 나 비트 맵이나 다른 것들의 정적 복사본을 저장하지 않으므로 메모리 부족 오류가 메모리 누수로 인한 것인지 궁금합니다.
해당 활동은 마지막 활동 계층입니다. 주요 활동 인 계층 구조의 루트에는 WeakReference가 포함 된 android Handler 객체와 Bluetooth 네트워킹 스레드를 관리하는 영구적 인 프래그먼트가 있습니다. 계층 구조의 두 번째 활동은 간단한 ListActivity입니다.
해당 활동의 상위 활동이이 활동에 대한 Java의 가비지 수집에 영향을 미칩니 까?
오리엔테이션 변경을 통해 AsyncTask의 재 부착을 어떻게 관리합니까? –
나는 아닙니다, 나는 다만 또 다른 한개를 달리고 오래된 것을 try-catch-forget 놓게하십시오. – user1843784
그래서 네 번 회전하면 4 비트의 AsyncTask가 각각의 비트 맵에있을 수 있습니다. –