現在、構成の変更中に高価なデータ構造を保持したいと考えています。Bundle
高価なデータ構造はパーセル化できないため、使用しないことにしました。
したがって、非 UI フラグメント ( RetainInstanceFragmentと呼ばれます) を使用setRetainInstance(true)
して、データ構造を保持します。
public class RetainInstanceFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Creating expensive data structure
expensiveDataStructure = CreateExpensiveDataStructure();
// Tell the framework to try to keep this fragment around
// during a configuration change.
setRetainInstance(true);
}
public ExpensiveDataStructure expensiveDataStructure = null;
}
UI フラグメント ( UIFragmentと呼ばれる) は、 から高価なデータ構造を取得しRetainInstanceFragment
ます。で設定が変更されるたびにUIFragment
、は、新しい を作成する前に、常にからUIFragment
「キャッシュ」を取得しようとします。RetainInstanceFragment
FragmentManager
RetainInstanceFragment
サンプルコードは以下の通りです。
public class UIFragment extends SherlockListFragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
FragmentManager fm = getFragmentManager();
// Check to see if we have retained the worker fragment.
retainInstanceFragment = (RetainInstanceFragment)fm.findFragmentByTag("data");
// If not retained (or first time running), we need to create it.
if (retainInstanceFragment == null) {
retainInstanceFragment = new RetainInstanceFragment();
fm.beginTransaction().add(watchlistArrayFragment, "data").commit();
} else {
// We can re-use retainInstanceFragment.expensiveDataStructure even
// after configuration change.
}
}
}
ただし、問題があります。古いものを破棄して新しいものにUIFragment
置き換えるときはいつでも、古いものも同様に破棄されることを期待しています。これが私が破壊して新しいものを作成する方法ですUIFragment
RetainInstanceFragment
UIFragment
public class MyFragmentActivity extends SlidingFragmentActivity
// Being triggered when there is different menu item in sliding menu being
// selected.
public void selectActiveContent(Country country) {
Fragment fragment = new UIFragment(country);
getSupportFragmentManager().beginTransaction().replace(R.id.content, fragment).commitAllowingStateLoss();
}
しかし、古いRetainInstanceFragment
ものは決して破壊されません。
私の推測では、おそらく でクリーンアップを実行するのを忘れているのでしょうUIFragment
。したがって、次のコードを追加します
UIフラグメント
@Override
public void onDetach() {
super.onDetach();
// To differentiate whether this is a configuration changes, or we are
// removing away this fragment?
if (this.isRemoving()) {
FragmentManager fm = getFragmentManager();
fm.beginTransaction().remove(retainInstanceFragment).commit();
}
}
ただし、常に機能するわけではありません。スライド メニューを数回クリックします。
1. selectActiveContent() -> Create new UIFragment and new RetainInstanceFragment
2. selectActiveContent() -> Create new UIFragment, but re-use previous RetainInstanceFragment. (Wrong behavior)
3. selectActiveContent() -> Create new UIFragment, and new RetainInstanceFragment.
4. selectActiveContent() -> Create new UIFragment, but re-use previous RetainInstanceFragment. (Wrong behavior)
保持されたインスタンスフラグメントを適切に削除する方法はありますか?