Остановить обработчик после того, как фрагмент был уничтожен

У меня есть Fragment который настраивает ListView и создает Handler для периодического обновления Listview . Однако похоже, что Handler все еще работает после того, как Fragment был уничтожен.

Ниже приведен код.

 @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; } 

Обновление ListView после уничтожения Fragment приводит к сбою приложения. Как заставить Handler останавливаться по мере уничтожения Fragment ? Я также хотел бы знать, какие последствия, если какое-либо приостановление приложения имеет и на Handler .

Solutions Collecting From Web of "Остановить обработчик после того, как фрагмент был уничтожен"

Вам нужно реализовать такой обработчик

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

Вам нужно сохранить ссылку на ваш обработчик и запустить его в фрагменте, а затем, когда фрагмент будет уничтожен, вам нужно удалить обратные вызовы из обработчика, проходящего в 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(); } 

Другой способ остановки обработчика с использованием WeakReference для фрагмента:

 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() является просто получателем для свойства mDestroyed фрагмента:

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

Кто-то отправил другой вопрос, похожий, и проблема связана с ошибкой в ChildFragmentManager . В основном, ChildFragmentManager заканчивается сломанным внутренним состоянием, когда он отделен от Activity . Посмотрите оригинальный ответ здесь.

Используйте Rxjava, лучше

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

Затем в вызове метода ondestroy ()

 RxUtils.unsubscribe(subscription);