Android: perdita di memoria a causa di AsyncTask
-
27-09-2019 - |
Domanda
mi sono bloccato con una perdita di memoria che non riesco a risolvere. Ho identificato in cui si verifica, utilizzando il MemoryAnalizer ma invano fatica a sbarazzarsi di esso. Ecco il codice:
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'attività è terminato su un clic del pulsante, in questo modo:
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 indicato la perdita di memoria a:
((myApp) getApplication ()) setBitmapX (BitmapFactory.decodeByteArray ((byte []) args [0], 0, ((byte []) args [0]) lunghezza).);.
Sono grato per ogni suggerimento, vi ringrazio in anticipo.
Soluzione
è la vostra spazzatura filo raccolti dopo OnPostExecute si chiama o è ancora nella memoria?
Un Async compito non sarà annullata o distrutte al momento in cui l'attività è respinto. Se il filo è più o meno leggero e finiture dopo un piccolo tempo, basta tenerlo in funzione e aggiungere un MyActivity.this. isFinishing () clausola nel metodo OnPostExecute ().
Il tuo compito memorizza un riferimento implicito alle vostre MyActivity.this attività, perché si tratta di una classe privata all'interno l'attività. Ciò significa che il vostro attività non saranno spazzatura raccolti fino a quando le uscite di attività.
Altri suggerimenti
Si può cercare sotto frammento di codice
protected void onPostExecute(Boolean result) {
if(YourActivity.this.isFinished()){
//to smomething here
}
}