フラグメントのインスタンス状態をバックスタックに正しく保存するにはどうすればよいでしょうか? 質問する

フラグメントのインスタンス状態をバックスタックに正しく保存するにはどうすればよいでしょうか? 質問する

SO で同様の質問の例を多数見つけましたが、残念ながら私の要件を満たす回答はありませんでした。

縦向きと横向きでレイアウトが異なり、バックスタックを使用しているため、setRetainState()構成変更ルーチンを使用したトリックを使用できません。

TextViews でユーザーに特定の情報を表示しますが、これはデフォルトのハンドラーには保存されません。アクティビティのみを使用してアプリケーションを作成する場合、次の方法がうまく機能しました。

TextView vstup;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.whatever);
    vstup = (TextView)findViewById(R.id.whatever);
    /* (...) */
}

@Override
public void onSaveInstanceState(Bundle state) {
    super.onSaveInstanceState(state);
    state.putCharSequence(App.VSTUP, vstup.getText());
}

@Override
public void onRestoreInstanceState(Bundle state) {
    super.onRestoreInstanceState(state);
    vstup.setText(state.getCharSequence(App.VSTUP));
}

sではFragment、これは非常に特殊な状況でのみ機能します。具体的には、フラグメントを置き換えてそれをバック スタックに入れ、新しいフラグメントが表示されている間に画面を回転すると、ひどく壊れます。私が理解しているところによると、古いフラグメントはonSaveInstanceState()置き換えられるときに への呼び出しを受け取らず、何らかの形で にリンクされたままになり、Activityこのメソッドは が存在しなくなったときに後で呼び出されるためView、 のいずれかを検索するとTextViewになりますNullPointerException

また、'sでは問題なかったとしても、 sでは my への参照を保持するのはTextViews得策ではないことがわかりました。その場合、 は実際に状態を保存しますが、フラグメントが非表示のときに画面を2 回回転させると、新しいインスタンスで呼び出されないため、問題が再発します。FragmentActivityonSaveInstanceState()onCreateView()

の状態をonDestroyView()何らかのBundle型クラス メンバー要素 (実際には 1 つの ではなく、より多くのデータTextView) に保存し、それをに保存することを考えましたonSaveInstanceState()が、他にも欠点があります。主に、フラグメント現在表示されている場合、2 つの関数の呼び出し順序が逆になるため、2 つの異なる状況を考慮する必要があります。もっと明確で正しい解決策があるはずです。

ベストアンサー1

インスタンスの状態を正しく保存するには、Fragment次の手順を実行する必要があります。

1.フラグメントで、オーバーライドしてインスタンスの状態を保存しonSaveInstanceState()、次のように復元しますonActivityCreated()

class MyFragment extends Fragment {

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        ...
        if (savedInstanceState != null) {
            //Restore the fragment's state here
        }
    }
    ...
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        
        //Save the fragment's state here
    }

}

2.重要な点として、アクティビティでは、フラグメントのインスタンスを に保存しonSaveInstanceState()、 で復元する必要がありますonCreate()

class MyActivity extends Activity {

    private MyFragment 

    public void onCreate(Bundle savedInstanceState) {
        ...
        if (savedInstanceState != null) {
            //Restore the fragment's instance
            mMyFragment = getSupportFragmentManager().getFragment(savedInstanceState, "myFragmentName");
            ...
        }
        ...
    }
    
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
            
        //Save the fragment's instance
        getSupportFragmentManager().putFragment(outState, "myFragmentName", mMyFragment);
    }

}

おすすめ記事