24

setRetainInstanceのドキュメントによると:

これは、バックスタックにないフラグメントでのみ使用できます。

それで私はそれで遊び始めました。

最初のフラグメントAを追加するアクティビティが1つあります

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content, new PackageFragment());
ft.commit

次に、このフラグメントから、親アクティビティからメソッドを実行して、フラグメントBをバックスタックに追加します。

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content, new OrderFragment());
ft.addToBackStack(null);
ft.commit();

次に、onCreate、onDestroy、onSaveInstanceState、onActivityCreated...などからログメッセージを作成します。

このプロセスの2つのバージョンを試します。各フラグメントでデバイスを回転させます。

  1. デフォルト

すべてが期待どおりです。onCreate、onDestroy on Fragments Fire

  1. setRetainInstance(true)

すべてが期待どおりですか?onCreate、onDestroyonfragmentsは起動しません

フラグメントがバックスタックにある間はすべてが機能しているようです。それでは、なぜドキュメントはそれを使用すべきではないと言っているのでしょうか。トラブルが発生する可能性のあるシナリオは何ですか?

ありがとう

4

1 に答える 1

26

更新された回答:

トラブルが発生する可能性のあるシナリオは何ですか?

Fragmentバックスタックにaを追加し、構成変更時BundleFragmentfromからonSaveInstanceState()toに渡す場合。onCreateView()呼び出しsetRetainInstance(true)は、構成のBundle変更時にをnullに設定します。

setRetainInstance(true)(使用すると冗長になるため、開発者が実際にこれを試みるかどうかonSaveInstanceState()はわかりませんが、APIドキュメントに記載されている動作が見られなかったため、この回答を作成しました)。

addToBackStack()との両方setRetainInstance(true)が呼び出された場合、のみを呼び出す場合と比較して、構成変更時にライフサイクルメソッドの呼び出しとパラメーター値がsetRetainInstance()部分的に変更されます。FragmentaddToBackStack()

addToBackStack()具体的には、以下のテストで、呼び出しのみと呼び出しの違いを調べ、setRetainInstance(true)構成の変更で何が起こるかを確認します。

呼び出しますaddToBackStack()が、しませんsetRetainInstance(true);

  • onCreate()onDestroy()呼ばれます。
  • から渡されたバンドルはonSaveInstanceState()、のパラメータとして受信されますonCreateView()

addToBackStack()との両方を呼び出すsetRetainInstance(true)

  • onCreate()onDestroy()は呼ばれません。これは、APIドキュメントで説明されています。
  • から渡されたバンドルonSaveInstanceState()はで受信されませんonCreateView()。渡されたBundleものはnullです。

ログに記録されたメソッド呼び出しとnullについてテストされたパラメーターを使用したテスト:

Activity

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    MyFragment fragment;
    if (savedInstanceState != null) {
        fragment = (MyFragment) getFragmentManager().findFragmentByTag("my_fragment_tag");
    } else {
        fragment = new MyFragment();
        FragmentTransaction t = getFragmentManager().beginTransaction();
        t.addToBackStack(null);//toggle this
        t.add(android.R.id.content, fragment, "my_fragment_tag").commit(); 
    }
}

Fragment

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setRetainInstance(true);//toggle this
}

@Override
public void onSaveInstanceState(Bundle outState) {
    outState.putString("test", "value");
    super.onSaveInstanceState(outState);
}

テスト1:呼び出されたときaddToBackStack()と呼び出されなかっsetRetainInstance(true)ときのフラグメントライフサイクル

  • onAttach()
  • onCreate()
  • onCreateView()
  • onActivityCreated()
  • onStart()
  • onResume()

[デバイスを縦向きから横向きに回転]

  • onPause()
  • onSaveInstanceState()
  • onStop()
  • onDestroyView()
  • onDestroy()
  • onDetach()
  • onAttach()
  • onCreate()
  • onCreateView()with bundle param!= null
  • onStart()
  • onResume()

テスト2および3:呼び出されたsetRetainInstance(true)addToBackStack()呼び出された/呼び出されなかった(同じ結果)を使用したフラグメントライフサイクル呼び出し:

  • onAttach()
  • onCreateView()
  • onActivityCreated()
  • onStart()
  • onResume()

[デバイスを縦向きから横向きに回転]

  • onPause()
  • onSaveInstanceState()
  • onStop()
  • onDestroyView()
  • onDetach()
  • onAttach()
  • onCreateView()with bundle param == null
  • onStart()
  • onResume()
于 2012-12-08T01:23:24.947 に答える