J'ai une Fragment
qui configure une ListView
et crée une Handler
pour mettre à jour la Listview
périodiquement. Cependant, il semble que la Handler
soit toujours exécutée après la destruction de la Fragment
.
Ce qui suit est le code.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//boilerplate code
final Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
assignAdapter();
handler.postDelayed(this, 15000);
}
});
return v;
}
La mise à jour de ListView
après la destruction de Fragment
provoque le blocage de l'application. Comment puis-je faire arrêter la Handler
au fur et à mesure que la Fragment
est détruite? J'aimerais également savoir quels effets, le cas échéant, une suspension de l'application a sur la variable Handler
.
Vous devez implémenter gestionnaire comme celui-ci
private Handler myHandler;
private Runnable myRunnable = new Runnable() {
@Override
public void run() {
//Do Something
}
};
@Override
public void onDestroy () {
mHandler.removeCallbacks(myRunnable);
super.onDestroy ();
}
Vous devez stocker une référence à votre gestionnaire et runnable dans le fragment, puis lorsque le fragment est détruit, vous devez supprimer callbacks du gestionnaire qui passe dans le runnable.
private Handler mHandler;
private Runnable mRunnable;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//boilerplate code
mRunnable = new Runnable() {
@Override
public void run() {
assignAdapter();
handler.postDelayed(this, 15000);
}
};
mHandler = new Handler(mRunnable);
mHandler.post();
return v;
}
@Override
public void onDestroy() {
mHandler.removeCallbacks(mRunnable);
super.onDestroy();
}
Une autre façon d'arrêter le gestionnaire à l'utilisation de WeakReference
au fragment:
static final class UpdateUIRunnable implements Runnable {
final WeakReference<RouteGuideFragment> weakRefToParent;
final Handler handler;
public UpdateUIRunnable(RouteGuideFragment fragment, Handler handler) {
weakRefToParent = new WeakReference<RouteGuideFragment>(fragment);
this.handler = handler;
}
public void scheduleNextRun() {
handler.postDelayed(this, INTERVAL_TO_REDRAW_UI);
}
@Override
public void run() {
RouteGuideFragment fragment = weakRefToParent.get();
if (fragment == null || fragment.hasBeenDestroyed()) {
Log.d("UIUpdateRunnable", "Killing updater -> fragment has been destroyed.");
return;
}
if (fragment.adapter != null) {
try {
fragment.adapter.forceUpdate();
} finally {
// schedule again
this.scheduleNextRun();
}
}
}
}
où fragment.hasBeenDestroyed()
est tout simplement un getter de la propriété mDestroyed
d'un fragment:
@Override
public void onDestroy() {
super.onDestroy();
mDestroyed = true;
}
Quelqu'un a posté une autre question similaire et le problème est dû à un bogue dans la ChildFragmentManager
. Fondamentalement, la ChildFragmentManager
se termine par un état interne cassé lorsqu'elle est détachée de la Activity
. Regardez le réponse originale ici