web-dev-qa-db-fra.com

Arrête le gestionnaire après la destruction du fragment

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.

12
Sandah Aung

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();
}
6
Nicholas Hall

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();
                }
            }
        }
    }

fragment.hasBeenDestroyed() est tout simplement un getter de la propriété mDestroyed d'un fragment:

@Override
public void onDestroy() {
    super.onDestroy();
    mDestroyed = true;
}
2
Kuba Spatny

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

0
Yaco Zaragoza