1. ホーム
  2. android

[解決済み] フラグメントのインスタンス状態をバックスタックに正しく保存する方法は?

2022-03-19 04:39:56

質問

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));
}

Fragment の場合、これは非常に特殊な状況でのみ機能します。具体的に言うと、恐ろしいほど壊れるのは、フラグメントを置き換えてバックスタックに入れ、新しいフラグメントが表示されている間に画面を回転させる場合です。私が理解したところでは、古いフラグメントは onSaveInstanceState() にリンクしたままです。 Activity で、このメソッドは後でその View はもう存在しないので、私の任意の TextView の結果は NullPointerException .

また、私の場合は、参照を維持することで TextViews を使うのは、あまり良いアイデアではありません。 Fragment の場合はOKだったとしても Activity 's. その場合 onSaveInstanceState() は実際に状態を保存していますが、画面を回転させると問題が再発します。 2回 フラグメントが非表示の場合、その onCreateView() は新しいインスタンスでは呼び出されません。

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

どのように解決するのですか?

のインスタンス状態を正しく保存するために 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);
    }

}