閉じる

ListFragmentの背景が透けて見える?

フラグメントを内包する Activityを作った時、以下のようなコードを書く。

class HogeActivity extends FragmentActivity{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tablet_activity);
getSupportFragmentManager().beginTransaction()
.add(R.id.FragmentContainer, HogeListFragment.newInstance())
.commit();
}
}

一見期待通りに動作するのだけど、画面遷移した時に Fragment.onSaveInstanceStateが呼ばれず、当然のように Fragment.onActivityCreatedに渡される savedInstanceStateも常に nullだったり、端末を回転させると Fragmentがダブって(重なって)表示されたりと微妙におかしな動作。

結論から言うと、画面遷移したり端末が回転されて Activityが再構築されたりしても Fragmentは生きっぱなしみたい。
生きっぱなしだから Fragment.onSaveInstanceStateで状態を保存する必要もないし、Fragment.onActivityCreatedで再構築する必要もない。
さらにバックスタック自体も生きっぱなし or 再構築されるようで、端末回転時に Activity.onCreateにて Fragmentを登録すると多重登録になってダブって表示されることになる。

ネットにあふれているコードはどれを見てもその辺何かをやっているようには見えないけど、実際に問題になっているので対策をする。*1
対策の内容はと言えば、「Activity.onCreate時に savedInstanceStateを見て nullの時だけ Fragmentの登録を行う」というだけ。
呼ばれているのを見たことがないけど、Fragment.onSaveInstanceState系も実装しておくに越したことはないと思う。

ちなみに XMLファイルに記述してやると毎回削除&再構築されるっぽい。

レイアウトファイルが変わった時とか、コンテナが消えた場合はどうなるんだろうね?

2013/01/18追記

activity – Android: Duplicating of fragments when using Support Fragment Manager – Stack Overflow」が同じ内容なのかな?

回答も「 onCreateにて savedInstanceStateを見ろ」と同じ結論。

2013/06/17追記

当然すぎて書いてないけど、addではなく replaceを使えば何も考えなくて済む。
Fragmentにデータを保持しないのであればそっちのが手っ取り早い。
Activityにデータを持たせるのと Fragmentにデータを持たせるのとどちらが正解なのかはわからん。

2013/07/13追記

結局の所、Fragment.onCreateViewを使うようなケースを考えると Activityにデータを持たせ、onCreateでは savedInstanceStateの値にかかわらず常に Replaceを使い、常に Replaceを使っても大丈夫なように組むのが正解なのかな?


*1 そもそも自分のコードが根本的に間違っているという可能性も高い。

コメントを残す

メールアドレスが公開されることはありません。必須項目には印がついています *

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)