Android:由于 AsyncTask 导致内存泄漏 [英] Android: Memory leak due to AsyncTask

查看:23
本文介绍了Android:由于 AsyncTask 导致内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了无法修复的内存泄漏问题.我使用 MemoryAnalizer 确定了它发生的位置,但我徒劳地努力摆脱它.代码如下:

I'm stuck with a memory leak that I cannot fix. I identified where it occurs, using the MemoryAnalizer but I vainly struggle to get rid of it. Here is the code:

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();
}

}

活动在单击按钮时终止,如下所示:

The activity is terminated on a button click, like this:

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 在以下位置指示内存泄漏:

MemoryAnalyzer indicated the memory leak at:

((myApp) getApplication()).setBitmapX(BitmapFactory.decodeByteArray((byte[]) args[0], 0, ((byte[])args[0]).length));

我很感激任何建议,在此先感谢您.

I am grateful for any suggestion, thank you in advance.

推荐答案

你的线程是在onPostExecute被调用后被垃圾回收了还是还在内存中?

Is your thread garbage collected after onPostExecute is called or is it still in the memory?

异步任务不会在活动被解除的那一刻被取消或销毁.如果您的线程或多或少是轻量级的并且在一段时间后完成,只需保持运行并添加 MyActivity.this.isFinishing() 子句在 onPostExecute() 方法中.

A Async Task will not be canceled or destroyed at the moment the activity is dismissed. If your thread is more or less lightweight and finishes after a small time, just keep it running and add a MyActivity.this.isFinishing() clause in the onPostExecute() method.

您的任务存储对您的活动 MyActivity.this 的隐式引用,因为它是活动内的私有类.这意味着在任务退出之前,您的 Activity 不会被垃圾收集.

Your Task stores a implicit reference to your Activity MyActivity.this because it is a private class inside the activity. This means that your Activity will not be garbage collected until the task exits.

这篇关于Android:由于 AsyncTask 导致内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆