web-dev-qa-db-ja.com

フラグメントが破棄された後にハンドラーを停止します

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にもどのような影響があるかについても知りたいです。

14
Sandah Aung

このようなハンドラーを実装する必要があります

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

@Override
public void onDestroy () {

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

}

ハンドラへの参照とランナブルへの参照をフラグメントに格納する必要があり、フラグメントが破棄されたら、ランナブルに渡されるハンドラからコールバックを削除する必要があります。

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

フラグメントに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;
}
_
2
Kuba Spatny

誰かが同様の別の質問を投稿しましたが、問題はChildFragmentManagerのバグが原因です。基本的に、ChildFragmentManagerActivityから切り離されると、内部状態が壊れます。 元の答えはこちら を見てください

0
Yaco Zaragoza

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);
0
Raghav Sharma