Android: утечка памяти из-за AsyncTask - PullRequest
4 голосов
/ 13 июня 2010

Я застрял с утечкой памяти, которую не могу исправить. Я определил, где это происходит, используя 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)); 1012 *

Я благодарен за любое предложение, спасибо заранее.

Ответы [ 2 ]

10 голосов
/ 14 июня 2010

Собирается ли ваш поток мусора после вызова onPostExecute или он все еще находится в памяти?

Асинхронное задание не будет отменено или уничтожено в момент прекращения действия. Если ваш поток более или менее легок и завершает работу через некоторое время, просто продолжите его и добавьте MyActivity.this. isFinishing () в методе onPostExecute ().

Ваша задача хранит неявную ссылку на вашу активность MyActivity.this, потому что это частный класс внутри действия. Это означает, что ваша активность не будет собираться мусором до тех пор, пока задача не будет завершена.

0 голосов
/ 25 августа 2017

Вы можете попробовать ниже фрагмент кода

protected void onPostExecute(Boolean result) {
    if(YourActivity.this.isFinished()){
        //to smomething here
    }
}
...