【发布时间】:2011-03-03 06:12:24
【问题描述】:
我遇到了无法修复的内存泄漏问题。我使用 MemoryAnalizer 确定了它发生的位置,但我徒劳地努力摆脱它。代码如下:
public class MyActivity extends Activity implements SurfaceHolder.Callback {
...
Camera.PictureCallback mPictureCallbackJpeg = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
try {
// log the action
Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
// Show the ProgressDialog on this thread
pd = ProgressDialog.show(MyActivity.this, "", "Préparation", true, false);
// Start a new thread that will manage the capture
new ManageCaptureTask().execute(data, c);
}
catch(Exception e){
AlertDialog.Builder dialog = new AlertDialog.Builder(MyActivity.this);
...
dialog.create().show();
}
}
class ManageCaptureTask extends AsyncTask<Object, Void, Boolean> {
protected Boolean doInBackground(Object... args) {
Boolean isSuccess = false;
// initialize the bitmap before the capture
((myApp) getApplication()).setBitmapX(null);
try{
// Check if it is a real device or an emulator
TelephonyManager telmgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String deviceID = telmgr.getDeviceId();
boolean isEmulator = "000000000000000".equalsIgnoreCase(deviceID);
// get the bitmap
if (isEmulator) {
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeFile(imageFileName));
} else {
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeByteArray((byte[]) args[0], 0, ((byte[])args[0]).length));
}
((myApp) getApplication()).setImageForDB(ImageTools.resizeBmp(((myApp) getApplication()).getBmp()));
// convert the bitmap into a grayscale image and display it in the preview
((myApp) getApplication()).setImage(makeGrayScale());
isSuccess = true;
}
catch (Exception connEx){
errorMessageFromBkgndThread = getString(R.string.errcapture);
}
return isSuccess;
}
protected void onPostExecute(Boolean result) {
// Pass the result data back to the main activity
if (MyActivity.this.pd != null) {
MyActivity.this.pd.dismiss();
}
if (result){
((ImageView) findViewById(R.id.apercu)).setImageBitmap(((myApp) getApplication()).getBmp());
((myApp) getApplication()).setBitmapX(null);
}
else{
// there was an error
ErrAlert();
}
}
}
};
private void ErrAlert(){
// notify the user about the error
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
...
dialog.create().show();
}
}
活动在单击按钮时终止,如下所示:
Button use = (Button) findViewById(R.id.use);
use.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity.this, NextActivity.class);
intent.putExtra("dbID", "-1");
intent.putExtra("category", category);
((myApp) getApplication()).setBitmapX(null);
MyActivity.this.startActivity(intent);
MyActivity.this.finish();
}
});
MemoryAnalyzer 指出内存泄漏:
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeByteArray((byte[]) args[0], 0, ((byte[])args[0]).length));
感谢您的任何建议,提前感谢您。
【问题讨论】:
-
半受过教育的猜测:你是否应该在完成
Bitmap对象后调用recycle()?此外,在您给出的上下文中,对PickerActivity.this的调用似乎没有意义。而且你应该缓存经常使用的(myApp) getApplication()调用。 -
Christopher,感谢您的回复,事实上 PickerActivity 是 MyActivity(我编辑了帖子);位图是在应用程序级别定义的,这就是我不回收它们的原因,因为我在后续活动中需要它们。调试应用程序和 MemoryAnalyzer 告诉我,即使 MyActivity 终止,ManageCaptureTask 仍然存在,这是我不知道该怎么做的:终止该异步任务。我编辑了帖子,添加了终止 MyActivity 并启动下一个活动的 onClick 事件。
-
我看到你在整个
Application中使用Bitmap,但看到你在某个时候将它设置为null,所以想知道它是否应该在那个时候回收。跨度>
标签: android memory memory-leaks android-asynctask