はじめに
Fragmentを使っていると、なんとなく commit() を使っている人は多いと思います。
ただ、commitNow() との違いを理解していないとタイミング依存のバグを生む可能性があります。
さっくり何が違うのか解説
- commit() → 非同期で実行される
- commitNow() → その場で即時実行される(同期)
commit() の挙動
supportFragmentManager.beginTransaction()
.replace(R.id.container, SampleFragment())
.commit()
このように使うことが多いと思いますが、このコードでは「すぐにFragmentが切り替わる」ように見えます。
ですが、実際はメインスレッドのキューに積まれるだけです。
なので、実際にはこのコードが呼ばれた時点ではまだFragmentは呼ばれていません。
具体的には、transactionが呼ばれたタイミングでFragmentが呼ばれます。
transactionが呼ばれていないままだと、上記の処理にこれを加えただけでは
val fragment = supportFragmentManager.findFragmentById(R.id.container)
fragmentがnullになってしまいます。
commitNow() の挙動
supportFragmentManager.beginTransaction()
.replace(R.id.container, SampleFragment())
.commitNow()
commit()違い、これはその場で即時実行され、findFragmentById()してもnullになりません。
使い分け
- BackStackに追加できない
- UIスレッドをブロックする
などの理由から、commitNow()にも制約があるため「じゃあ commitNow() だけ使えばいい」というわけではありません。
では、どんな時にcommitNow()にすればいいのかですが、
- すぐにFragmentを参照したいとき
- 初期化処理
などです。それ以外の通常の画面遷移の時はcommit()を使うことをおすすめします。