Saya mengembangkan aplikasi menggunakan Android 4.0 ICS dan fragmen.
Pertimbangkan contoh yang dimodifikasi ini dari aplikasi contoh demo API ICS 4.0.3 (API level 15):
public class FragmentTabs extends Activity {
private static final String TAG = FragmentTabs.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.addTab(bar.newTab()
.setText("Simple")
.setTabListener(new TabListener<SimpleFragment>(
this, "mysimple", SimpleFragment.class)));
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
Log.d(TAG, "FragmentTabs.onCreate tab: " + savedInstanceState.getInt("tab"));
Log.d(TAG, "FragmentTabs.onCreate number: " + savedInstanceState.getInt("number"));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
}
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
private final Activity mActivity;
private final String mTag;
private final Class<T> mClass;
private final Bundle mArgs;
private Fragment mFragment;
public TabListener(Activity activity, String tag, Class<T> clz) {
this(activity, tag, clz, null);
}
public TabListener(Activity activity, String tag, Class<T> clz, Bundle args) {
mActivity = activity;
mTag = tag;
mClass = clz;
mArgs = args;
// Check to see if we already have a fragment for this tab, probably
// from a previously saved state. If so, deactivate it, because our
// initial state is that a tab isn't shown.
mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
if (mFragment != null && !mFragment.isDetached()) {
Log.d(TAG, "constructor: detaching fragment " + mTag);
FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
ft.detach(mFragment);
ft.commit();
}
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mFragment == null) {
mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
Log.d(TAG, "onTabSelected adding fragment " + mTag);
ft.add(android.R.id.content, mFragment, mTag);
} else {
Log.d(TAG, "onTabSelected attaching fragment " + mTag);
ft.attach(mFragment);
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (mFragment != null) {
Log.d(TAG, "onTabUnselected detaching fragment " + mTag);
ft.detach(mFragment);
}
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT).show();
}
}
public static class SimpleFragment extends Fragment {
TextView textView;
int mNum;
/**
* When creating, retrieve this instance's number from its arguments.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(FragmentTabs.TAG, "onCreate " + (savedInstanceState != null ? ("state " + savedInstanceState.getInt("number")) : "no state"));
if(savedInstanceState != null) {
mNum = savedInstanceState.getInt("number");
} else {
mNum = 25;
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
Log.d(TAG, "onActivityCreated");
if(savedInstanceState != null) {
Log.d(TAG, "saved variable number: " + savedInstanceState.getInt("number"));
}
super.onActivityCreated(savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState) {
Log.d(TAG, "onSaveInstanceState saving: " + mNum);
outState.putInt("number", mNum);
super.onSaveInstanceState(outState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(FragmentTabs.TAG, "onCreateView " + (savedInstanceState != null ? ("state: " + savedInstanceState.getInt("number")) : "no state"));
textView = new TextView(getActivity());
textView.setText("Hello world: " + mNum);
textView.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
return textView;
}
}
}
Berikut adalah keluaran yang diambil dari menjalankan contoh ini dan kemudian memutar telepon:
06-11 11:31:42.559: D/FragmentTabs(10726): onTabSelected adding fragment mysimple
06-11 11:31:42.559: D/FragmentTabs(10726): onCreate no state
06-11 11:31:42.559: D/FragmentTabs(10726): onCreateView no state
06-11 11:31:42.567: D/FragmentTabs(10726): onActivityCreated
06-11 11:31:45.286: D/FragmentTabs(10726): onSaveInstanceState saving: 25
06-11 11:31:45.325: D/FragmentTabs(10726): onCreate state 25
06-11 11:31:45.340: D/FragmentTabs(10726): constructor: detaching fragment mysimple
06-11 11:31:45.340: D/FragmentTabs(10726): onTabSelected attaching fragment mysimple
06-11 11:31:45.348: D/FragmentTabs(10726): FragmentTabs.onCreate tab: 0
06-11 11:31:45.348: D/FragmentTabs(10726): FragmentTabs.onCreate number: 0
06-11 11:31:45.348: D/FragmentTabs(10726): onCreateView state: 25
06-11 11:31:45.348: D/FragmentTabs(10726): onActivityCreated
06-11 11:31:45.348: D/FragmentTabs(10726): saved variable number: 25
06-11 11:31:45.348: D/FragmentTabs(10726): onCreateView no state
06-11 11:31:45.348: D/FragmentTabs(10726): onActivityCreated
Pertanyaan saya adalah, mengapa onCreateView dan onActivityCreated dipanggil dua kali? Pertama kali dengan Bundle dengan status tersimpan dan kedua kalinya dengan null storedInstanceState?
Ini menyebabkan masalah dengan mempertahankan status fragmen saat diputar.