Je suis coincé avec une fuite de mémoire que je ne peux pas réparer. J'ai identifié où il se produit, en utilisant le MemoryAnalizer mais j'ai vainement du mal à m'en débarrasser. Voici le code:Android: fuite de mémoire due à AsyncTask
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();
}
}
L'activité se termine sur un bouton clic, comme ceci:
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 indique la fuite de mémoire à:
((myApp) getApplication()). setBitmapX (BitmapFactory.decodeByteArray ((byte []) arguments [0], 0, ((byte []) arguments [0]). length));
Je suis reconnaissant pour toute suggestion, merci d'avance.
estimation semi-éduquée: si vous appellerez 'recycler()' 'sur vos objets Bitmap' une fois que vous avez terminé avec eux? En outre, l'appel à 'PickerActivity.this' ne semble pas avoir de sens dans le contexte que vous avez donné. Et vous devriez mettre en cache l'appel '(myApp) getApplication()' qui est si souvent utilisé. –
Christopher, Merci pour votre réponse, en effet PickerActivity est MyActivity (j'ai édité le post); les bitmaps sont définis au niveau de l'application, c'est pourquoi je ne les recycle pas, car j'en ai besoin dans les activités suivantes. Le débogage de l'application et MemoryAnalyzer m'indiquent que ManageCaptureTask persiste même lorsque MyActivity est terminé et c'est ce que je ne sais pas comment faire: terminer cette tâche asynchrone. J'ai modifié le post, en ajoutant l'événement onClick où MyActivity est terminé et l'activité suivante est lancée. – Manu
J'ai vu que vous utilisiez 'Bitmap' dans' Application', mais vous avez vu que vous l'avez défini sur 'null' à un moment donné, alors je me suis demandé si cela devrait être recyclé à ce moment-là. –