Stop handler after the fragment has been destroyed

旧时模样 提交于 2019-12-04 00:09:22

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

}

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

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;
}
Yaco Zaragoza

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

Use Rxjava, its better

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

private void whatToDo() {
   System.out.println("Called after 1 second");
}

Then in ondestroy() method call

RxUtils.unsubscribe(subscription);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!