Integrate from support lib: fix restore of list state.
The FragmentManager/ListFragment impl was restoring the list
state before setting its adapter. This caused the list view to
lose the state, since it gets cleared as part of setting the
adapter. Now the fragment manager waits on restoring the view
hierarchy state until after it has done onActivityCreated(),
at which point we have set the adapter.
It would be nice to make list view less fragile in this regard,
but that is for a different change.
Change-Id: I032d6fe0fefc0dabfae95d44152146029ef5db8e
diff --git a/api/current.txt b/api/current.txt
index 374c415..975444e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2851,6 +2851,7 @@
method public void onSaveInstanceState(android.os.Bundle);
method public void onStart();
method public void onStop();
+ method public void onViewCreated(android.view.View, android.os.Bundle);
method public void registerForContextMenu(android.view.View);
method public void setArguments(android.os.Bundle);
method public void setHasOptionsMenu(boolean);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index a528a1aa..dd158f9 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -326,8 +326,9 @@
static final int INITIALIZING = 0; // Not yet created.
static final int CREATED = 1; // Created.
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
- static final int STARTED = 3; // Created and started, not resumed.
- static final int RESUMED = 4; // Created started and resumed.
+ static final int STOPPED = 3; // Fully created, not started.
+ static final int STARTED = 4; // Created and started, not resumed.
+ static final int RESUMED = 5; // Created started and resumed.
int mState = INITIALIZING;
@@ -959,6 +960,19 @@
}
/**
+ * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
+ * has returned, but before any saved state has been restored in to the view.
+ * This gives subclasses a chance to initialize themselves once
+ * they know their view hierarchy has been completely created. The fragment's
+ * view hierarchy is not however attached to its parent at this point.
+ * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
+ * @param savedInstanceState If non-null, this fragment is being re-constructed
+ * from a previous saved state as given here.
+ */
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ }
+
+ /**
* Called to have the fragment instantiate its user interface view.
* This is optional, and non-graphical fragments can return null (which
* is the default implementation). This will be called between
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 1eaca3b..0da656f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -714,13 +714,14 @@
null, f.mSavedFragmentState);
if (f.mView != null) {
f.mView.setSaveFromParentEnabled(false);
+ if (f.mHidden) f.mView.setVisibility(View.GONE);
f.restoreViewState();
- if (f.mHidden) f.mView.setVisibility(View.GONE);
+ f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
case Fragment.CREATED:
if (newState > Fragment.CREATED) {
- if (DEBUG) Log.v(TAG, "moveto CONTENT: " + f);
+ if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
@@ -744,9 +745,10 @@
anim.start();
}
container.addView(f.mView);
- f.restoreViewState();
}
- if (f.mHidden) f.mView.setVisibility(View.GONE);
+ if (f.mHidden) f.mView.setVisibility(View.GONE);
+ f.restoreViewState();
+ f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
@@ -756,10 +758,13 @@
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onActivityCreated()");
}
+ if (f.mView != null) {
+ }
f.mSavedFragmentState = null;
}
case Fragment.ACTIVITY_CREATED:
- if (newState > Fragment.ACTIVITY_CREATED) {
+ case Fragment.STOPPED:
+ if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.mCalled = false;
f.onStart();
@@ -803,9 +808,10 @@
+ " did not call through to super.onStop()");
}
}
+ case Fragment.STOPPED:
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
- if (DEBUG) Log.v(TAG, "movefrom CONTENT: " + f);
+ if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
if (f.mView != null) {
// Need to save the current view state if not
// done already.
@@ -1631,7 +1637,7 @@
}
public void dispatchStop() {
- moveToState(Fragment.ACTIVITY_CREATED, false);
+ moveToState(Fragment.STOPPED, false);
}
public void dispatchDestroy() {
diff --git a/core/java/android/app/ListFragment.java b/core/java/android/app/ListFragment.java
index 6e2f4b6..a5ee26c 100644
--- a/core/java/android/app/ListFragment.java
+++ b/core/java/android/app/ListFragment.java
@@ -195,11 +195,11 @@
}
/**
- * Attach to list view once Fragment is ready to run.
+ * Attach to list view once the view hierarchy has been created.
*/
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
ensureList();
}