web-dev-qa-db-ja.com

フラグメントonSaveInstanceState()が呼び出されないのはなぜですか?

独自の状態(選択されたボタンなど)を持つフラグメントがあります。その状態は画面の回転で失われます。

フラグメントを含むアクティビティの/ res/layout /には縦向きのレイアウトがあり、/ res/layout-land /にはほぼ同じ横向きのレイアウトがあります。どちらのレイアウトにも、次のようなフラグメントが含まれています。

_<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent">
    <fragment
        Android:id="@+id/testFragment"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        class="au.com.x.y.TestFragment" />
...</LinearLayout>
_

私がテストしてきたフラグメントクラスは次のとおりです。

_public class TestFragment extends Android.support.v4.app.Fragment {
    private static final String TAG = "TestFragment";
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate(): " + 
                (savedInstanceState != null ? "NOT NULL" : "NULL"));
    }
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.i(TAG, "onActivityCreated(): " + 
                (savedInstanceState != null ? "NOT NULL" : "NULL"));
    }
    public void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        Log.i(TAG, "onSaveInstanceState()");
        state.putString("saved_thing", "some_value");
    }
    public View onCreateView(
        LayoutInflater inflater,
        ViewGroup container,
        Bundle b) { ... }
}
_

ActionBarSherlockを介して導入されたフラグメントに3.0より前のサポートパッケージを使用していることに注意してください。

LogCatは私に:

_BEFORE SCREEN ROTATION (PORTRAIT):
02-23 11:45:58.015: I/TestFragment(22629): onCreate(): NULL
02-23 11:45:58.015: I/TestFragment(22629): onCreateView()
02-23 11:45:58.035: I/TestFragment(22629): onActivityCreated(): NULL
AFTER SCREEN ROTATION (LANDSCAPE):
02-23 11:46:00.615: I/TestFragment(22629): onCreate(): NULL
02-23 11:46:00.615: I/TestFragment(22629): onCreateView()
02-23 11:46:00.635: I/TestFragment(22629): onActivityCreated(): NULL
_

ご覧のとおり、onSaveInstanceState()が呼び出されることはなく、フラグメントはonCreate()onActivityCreated()の両方で常にnullsavedInstanceStateを取得します。

アクティビティmyFragment.setRetainInstance(true)onCreate()を試しましたが、何も変わりません。

私のonSaveInstanceState()には@Overrideがあるので、タイプミスのような愚かなことではないことがわかります。

ActionBarSherlockの例の1つ(com.actionbarsherlock.sample.shakespeare)と、そこにあるフラグメントのonSaveInstanceState()メソッドが適切に呼び出されていることを確認しました。私の知る限り、その例は私のコードがどのように記述されているかを正確に記述しています—レイアウトとレイアウトランドXMLの両方に含まれるフラグメントです。メインプロジェクトが使用しているのとまったく同じバージョンのActionBarSherlockを使用してそのサンプルを作成したこともあり、その例ではインスタンスの状態を保存しても問題なく機能します。

画面の回転全体でフラグメントの状態を保持するにはどうすればよいですか? onSaveInstanceState()が呼び出されないのはなぜですか?

13
George

myFragment.setRetainInstance(true)を有効にして状態を保持できますが、これは「自動的に」行われます。つまり、クラスメンバーに割り当てられた値を保持し、onSaveInstanceStateを使用しません(したがって、savedInstanceStateは常にnullです)。

このフラグメントをホストするFragmentActivityonSaveInstanceStateをオーバーライドしないことを確認してください。オーバーライドする場合は、super.onSaveInstanceState(Bundle)を呼び出す必要があります。

23
Eric Kok

フラグメントが回転したときに別のレイアウトリソースが必要な場合、setRetainInstance(true)は使用できません。この page は、setRetainInstance(true)を使用したフラグメントのライフサイクルを示しています。

元のアイデアは、通常のアクティビティと同様に、onSaveInstanceState()を使用してすべてのメンバーデータを保持することです。ただし、何らかの理由で、onSaveInstanceState()は呼び出されません。しかし、@ Eric Kokが示唆したように、FragmentActivityは正しいです)。私が見つけた最善の解決策は、フラグメントの引数を使用することです。

solution by Fyodor Volchyok を参照してください。簡単です。 onSaveInstanceState()ではoutState、onViewCreated()ではsavedInstanceStateのように機能します。

0
John Pang