web-dev-qa-db-ja.com

新しいFragmentTransaction commitNow()は内部でどのように機能しますか?

新しい commitNow() メソッドがAndroid Nおよびサポートライブラリバージョン24に追加されました。

このトランザクションを同期的にコミットします。追加されたフラグメントはすべて初期化され、ホストのライフサイクル状態に完全に移行します。削除されたフラグメントは、この呼び出しが戻る前に破棄されます。この方法でトランザクションをコミットすると、フラグメントをホストのライフサイクル状態を監視する専用のカプセル化されたコンポーネントとして追加することができます。ビューを管理するフラグメントには、これらのビューが作成および添付されます。

CommitNowを呼び出すことは、commit()を呼び出してからFragmentManager.executePendingTransactions()を呼び出すことよりも望ましいです。

この方法でコミットされたトランザクションは、FragmentManagerのバックスタックに追加されない可能性があります。そうすると、他の非同期にコミットされたトランザクションに対する他の予想される順序の保証が壊れます。このメソッドは、addToBackStack(String)を使用してバックスタックに追加することを以前に要求したトランザクションの場合、IllegalStateExceptionをスローします。

トランザクションは、状態を保存するアクティビティを含む前に、このメソッドでのみコミットできます。その時点以降にコミットが試行されると、例外がスローされます。これは、アクティビティをその状態から復元する必要がある場合、コミット後の状態が失われる可能性があるためです。コミットを失ってもよい状況については、commitAllowingStateLoss()を参照してください。

分かりにくいと思う部分を太字で強調しています。

だから、私の主な懸念/質問は次のとおりです。

1-追加できない場合がありますか? IllegalStateExceptionを受け取ると言われているので、追加されるのか追加されないのか?

2-バックスタックにフラグメントを追加する場合、これを使用できないという事実を受け入れます。それが言っていないのは、この例外が発生するということです:

_Java.lang.IllegalStateException: This transaction is already being added to the back stack
_

!!!! ????

内部で呼び出しているため、自分でaddToBackStack(String)を呼び出すことはできませんか?申し訳ありませんが...何ですか?どうして?バックスタックに追加したくない場合はどうすればよいですか?そして、後でバックスタックからそのフラグメントを使用しようとしたが、追加されない可能性があるため、後で存在しない場合はどうなりますか?

commitAllowingStateLoss()を使用していた場合、これは予期されるもののように見えますが、commitNowAllowingStateLoss()も存在することがわかります。そのため、どのようなロジックに従うのでしょうか。

TL; DR

バックスタックに関してcommitNow()は内部的にどのように機能しますか?

53
Kaizie

このような質問に直面したとき、Androidソースコードはオープンソースです!

回答

それでは、BackStackRecordのソースを見てみましょう here

_@Override
public void commitNow() {
    disallowAddToBackStack();
    mManager.execSingleAction(this, false);
}

@Override
public FragmentTransaction disallowAddToBackStack() {
    if (mAddToBackStack) {
        throw new IllegalStateException(
                "This transaction is already being added to the back stack");
    }
    mAllowAddToBackStack = false;
    return this;
}
_

また、トランザクションでmAddToBackStackを呼び出すと、addToBackStackはtrueに設定されます。

したがって、あなたの質問に答えるために、commitNow()を呼び出すときにaddToBackStackが内部的に呼び出されることはありません。これは、あいまいな例外メッセージです。現在のメッセージの代わりにYou're not allowed to add to backstack when using commitNow()と言うべきだと思います。

ボーナス:

FragmentManagerのソースコードをさらに掘り下げてみると、 herecommitNow()が実際にalmostと同じことをexecutePendingTransactions()は上記のようですが、以前にコミットされたすべてのトランザクションを実行する代わりに、commitNow()はそのトランザクションのみをコミットします。

これが、他の保留中のトランザクションがないことを保証できないため、commitNow()がバックスタックへの追加を許可しない主な理由だと思います。 commitNow()がバックスタックに追加できる場合、バックスタックシーケンスを壊して予期せぬ事態を引き起こす可能性があります。

77