Ho passato un gestore creato sul thread mainUI da Activity
e passato a un thread che esegue alcune operazioni di rete e quando ottengo risultato invio il risultato all'attività utilizzando il gestore .L'istanza dell'attività esiste ancora anche dopo che onDestroy() è chiamato
Questo approccio ha avuto problema a perdite di memoria quando sono andato attraverso questi link:
Inner ClassHandler Memory Leak
Android Developers
così ho dovuto implementato WeakReference
, e ha mantenuto l'istanza di attività utilizzando WeakReference
. Ma sto ancora vedendo l'istanza Activity
viva anche dopo che l'attività è stata distrutta.
Ho creato un'attività interna Handler
e ho passato l'istanza di attività come weakreference al gestore.
Nel momento in cui il mio Handler
risponde con un messaggio recapitato dopo 10 secondi, Activity
viene distrutto. Ma il riferimento debole ha ancora l'istanza Activity
e sto vedendo il Toast
, dopo che Activity
è stato distrutto.
C'è qualcosa in cui la mia comprensione è sbagliata?
Qualcuno può spiegare come gestire i messaggi consegnati a un gestore, ma l'interfaccia utente non è in giro?
import java.lang.ref.WeakReference;
import android.os.Handler;
import android.os.Message;
public abstract class SingleParamHandler <T> extends Handler
{
private WeakReference<T> mActivityReference;
public SingleParamHandler(T activity) {
mActivityReference = new WeakReference<T>(activity);
}
@Override
public void handleMessage(Message msg) {
if (mActivityReference.get() == null) {
return;
}
handleMessage(mActivityReference.get(), msg);
}
protected abstract void handleMessage(T activity, Message msg);
}
import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.widget.Toast;
public class MainActivity extends Activity {
MyHandler<MainActivity> handler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main1);
handler = new MyHandler<MainActivity>(this);
new Thread(new MyRunnable(handler)).start();
}
public void onDestroy() {
super.onDestroy();
System.out.println("######## Activity onDestroy() ###### ");
}
private class MyRunnable implements Runnable {
private Handler mHandler;
public MyRunnable(Handler handler) {
mHandler = handler;
}
public void run() {
try {
Thread.sleep(10000);
mHandler.sendMessage(Message.obtain(handler, 1));
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static class MyHandler<T> extends SingleParamHandler<T> {
public MyHandler(T activity) {
super(activity);
}
@Override
public void handleMessage(T act, Message msg) {
if(msg.what == 1) {
Toast.makeText((MainActivity)act, "Called after activity destroyed", Toast.LENGTH_LONG).show();;
}
}
}
}
Sulla base della risposta ottenuta , sto aggiornando la risposta qui. Puoi farlo nel modo in cui ti è piaciuto. Ma questo è un modo.
Aggiunta la funzione di seguito in SingleParamHandler
public void clear() {
mActivityReference.clear();
}
e nell'attività OnDestroy()
public void onDestroy() {
super.onDestroy();
System.out.println("######## Activity onDestroy() ###### ");
handler.clear();
}
Grazie per la logica. Posso sapere, cosa ti fa dire che il riferimento debole non è necessario, perché il link che ho postato dice che Handler deve essere statico e rendere debole riferimento all'attività o al servizio e controllare prima di gestire il messaggio? non è che contraddice? La tua conoscenza su questo sarebbe apprezzata .. !! – Mani
@Mani Questo suggerimento va nella stessa direzione del mio (registrazione/annullamento delle attività). Stavo solo facendo meno ipotesi. David, penso ancora in questo semplice scenario, sarebbe più facile se il Gestore controlli 'Activity.isDestroyed()', perché 'onDestroy()' non è garantito per l'esecuzione? –
L'articolo che hai collegato copre una situazione specifica e non sono d'accordo con tutto ciò che è scritto lì. Il caso trattato è un "messaggio ritardato" pubblicato su un 'Handler'. L'articolo descrive un caso in cui un messaggio viene pubblicato su un 'Handler' che verrà consegnato in 10 minuti. Questo messaggio ha un riferimento al 'Handler' e il' Handler' ha un riferimento al 'Activity' e questo implica che né il' Handler' né il 'Activity' potranno essere rimossi dal garbage collector ** mentre questo messaggio è ancora in coda **. –