Stop handler after the fragment has been destroyed
Asked Answered
F

4

19

I have a Fragment which sets up a ListView and creates a Handler to update the Listview periodically. However, it looks like the Handler still runs after the Fragment has been destroyed.

The following is the 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;
}

Updating the ListView after the destruction of the Fragment causes the app to crash. How can I cause the Handler to stop as the Fragment gets destroyed? I would also like to know what effects if any pausing the app has on the Handler as well.

Fluted answered 21/4, 2015 at 13:43 Comment(0)
S
31

You need to implement handler like this

private Handler myHandler;
private Runnable myRunnable = new Runnable() {
    @Override
    public void run() {
        //Do Something
    }
};

@Override
public void onDestroy () {

    mHandler.removeCallbacks(myRunnable);
    super.onDestroy ();

}
Samala answered 21/4, 2015 at 13:45 Comment(0)
B
6

You need to store a reference to your handler and runnable in the fragment, and then when the fragment is destroyed you need to remove callbacks from the handler passing in the 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();
}
Barracks answered 21/4, 2015 at 13:53 Comment(2)
I placed in onDetach().Sulphurate
The implementation has been changed overtime but still works. You just need to change it to handler = new Handler(); handler.post(runnable);Swaine
O
2

Another way of stopping the handler with the use of WeakReference to the 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();
                }
            }
        }
    }

where fragment.hasBeenDestroyed() is simply a getter for mDestroyed property of a fragment:

@Override
public void onDestroy() {
    super.onDestroy();
    mDestroyed = true;
}
Outweigh answered 21/4, 2015 at 22:40 Comment(1)
it is effective way to avoid NPE error while updating view :) good workAdvancement
K
0

Someone posted another question similar and the problem is due to a bug in the ChildFragmentManager. Basically, the ChildFragmentManager ends up with a broken internal state when it is detached from the Activity. Have a look at the original answer here

Kippie answered 21/4, 2015 at 13:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.