Остановить обработчик после того, как фрагмент был уничтожен
У меня есть Fragment
, который устанавливает a ListView
и создает a 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
.
Ответы
Ответ 1
Вам нужно реализовать такой обработчик
private Handler myHandler;
private Runnable myRunnable = new Runnable() {
@Override
public void run() {
//Do Something
}
};
@Override
public void onDestroy () {
mHandler.removeCallbacks(myRunnable);
super.onDestroy ();
}
Ответ 2
Вам нужно сохранить ссылку на ваш обработчик и запустить его в фрагменте, а затем, когда фрагмент будет уничтожен, вам нужно удалить обратные вызовы из обработчика, проходящего в 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();
}
Ответ 3
Другой способ остановки обработчика с использованием 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;
}
Ответ 4
Кто-то отправил другой вопрос, похожий, и проблема связана с ошибкой в ChildFragmentManager
. В принципе, ChildFragmentManager
заканчивается сломанным внутренним состоянием, когда он отсоединен от Activity
. Посмотрите оригинальный ответ здесь
Ответ 5
Используйте 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);