Skip to content Skip to sidebar Skip to footer

Stop Handler After The Fragment Has Been Destroyed

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 dest

Solution 1:

You need to implement handler like this

private Handler myHandler;
privateRunnablemyRunnable=newRunnable() {
    @Overridepublicvoidrun() {
        //Do Something
    }
};

@OverridepublicvoidonDestroy() {

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

}

Solution 2:

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.

privateHandler mHandler;
privateRunnable mRunnable;

@OverridepublicViewonCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    //boilerplate code

    mRunnable = newRunnable() {
        @Overridepublicvoidrun() {
            assignAdapter();
            handler.postDelayed(this, 15000);
        }
    };

    mHandler = newHandler(mRunnable);
    mHandler.post();

    return v;
}

@OverridepublicvoidonDestroy() {
    mHandler.removeCallbacks(mRunnable);
    super.onDestroy();
}

Solution 3:

Another way of stopping the handler with the use of WeakReference to the fragment:

staticfinalclassUpdateUIRunnableimplementsRunnable {

        final WeakReference<RouteGuideFragment> weakRefToParent;
        final Handler handler;

        publicUpdateUIRunnable(RouteGuideFragment fragment, Handler handler) {
            weakRefToParent = newWeakReference<RouteGuideFragment>(fragment);
            this.handler = handler;
        }

        publicvoidscheduleNextRun() {
            handler.postDelayed(this, INTERVAL_TO_REDRAW_UI);
        }

        @Overridepublicvoidrun() {
            RouteGuideFragmentfragment= 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 againthis.scheduleNextRun();
                }
            }
        }
    }

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

@OverridepublicvoidonDestroy() {
    super.onDestroy();
    mDestroyed = true;
}

Solution 4:

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

Solution 5:

Use Rxjava, its better

subscription = Observable.timer(1000, TimeUnit.MILLISECONDS)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(aLong -> whatToDo());

privatevoidwhatToDo() {
   System.out.println("Called after 1 second");
}

Then in ondestroy() method call

RxUtils.unsubscribe(subscription);

Post a Comment for "Stop Handler After The Fragment Has Been Destroyed"