summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2010-09-11 20:52:31 -0700
committerDianne Hackborn <hackbod@google.com>2010-09-12 17:10:04 -0700
commit3e449ce00ed2d3b271e50bc7a52798f630973bf1 (patch)
tree94038ccfea9e3412b770b3478853e7f83129c9b5
parent2f761760459fe27c8e9f96569bb7f28fc5b58bab (diff)
downloadframeworks_base-3e449ce00ed2d3b271e50bc7a52798f630973bf1.zip
frameworks_base-3e449ce00ed2d3b271e50bc7a52798f630973bf1.tar.gz
frameworks_base-3e449ce00ed2d3b271e50bc7a52798f630973bf1.tar.bz2
Some fragment stuff:
Fix issue #2975886: Make getTargetFragment() survive rotation events with retained fragments. We now fix up the fragment pointer when restoring state. Fix issue #2919928: In PreferenceFragment, addPreferencesFromResources() is not effective when called after onActivityCreated(). Note to self: do not use a what code of 0. Maybe that should be documented (I'll do it in gingerbread). Hopefully implement #2992753: DialogFragment.dismiss will NPE if called too soon (before attached to activity). We now keep track of the FragmentManager separately from the activity, and set that as soon as the fragment is part of a transaction. Investigate issue #2988876: NPE when device orientation is changed. The NPE is because of the app trying to do a fragment transaction in onPause(). This is fundamentally not viable, since (a) the activity will be gone before we ever have a chance to process the message to commit the transaction, and (b) even if we did try to commit the transaction earlier, this would be done after onSaveInstanceState() and thus not work in cases where the activity gets killed in the background. So instead, we'll just throw an immediate exception if you try to do this. Change-Id: Iea62b50eb79f066af2471fce86836d073398f4f7
-rw-r--r--core/java/android/app/Activity.java1
-rw-r--r--core/java/android/app/BackStackEntry.java1
-rw-r--r--core/java/android/app/Fragment.java13
-rw-r--r--core/java/android/app/FragmentManager.java28
-rw-r--r--core/java/android/preference/PreferenceActivity.java4
-rw-r--r--core/java/android/preference/PreferenceFragment.java2
6 files changed, 44 insertions, 5 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 3dcdc0a..97aa23e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4058,6 +4058,7 @@ public class Activity extends ContextThemeWrapper
fragment.mFragmentId = id;
fragment.mTag = tag;
fragment.mImmediateActivity = this;
+ fragment.mFragmentManager = mFragments;
// If this fragment is newly instantiated (either right now, or
// from last saved state), then give it the attributes to
// initialize itself.
diff --git a/core/java/android/app/BackStackEntry.java b/core/java/android/app/BackStackEntry.java
index 71fd5e5..296b495 100644
--- a/core/java/android/app/BackStackEntry.java
+++ b/core/java/android/app/BackStackEntry.java
@@ -205,6 +205,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
throw new IllegalStateException("Fragment already added: " + fragment);
}
fragment.mImmediateActivity = mManager.mActivity;
+ fragment.mFragmentManager = mManager;
if (tag != null) {
if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 909e81f..1cbed79 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -94,6 +94,7 @@ final class FragmentState implements Parcelable {
mInstance.mContainerId = mContainerId;
mInstance.mTag = mTag;
mInstance.mRetainInstance = mRetainInstance;
+ mInstance.mFragmentManager = activity.mFragments;
return mInstance;
}
@@ -318,6 +319,11 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
// Number of active back stack entries this fragment is in.
int mBackStackNesting;
+ // The fragment manager we are associated with. Set as soon as the
+ // fragment is used in a transaction; cleared after it has been removed
+ // from all transactions.
+ FragmentManager mFragmentManager;
+
// Set as soon as a fragment is added to a transaction (or removed),
// to be able to do validation.
Activity mImmediateActivity;
@@ -578,10 +584,13 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
/**
* Return the FragmentManager for interacting with fragments associated
- * with this fragment's activity.
+ * with this fragment's activity. Note that this will be non-null slightly
+ * before {@link #getActivity()}, in the time from when the fragment is
+ * placed in a {@link FragmentTransaction} until it is committed and
+ * attached to its activity.
*/
final public FragmentManager getFragmentManager() {
- return mActivity.mFragments;
+ return mFragmentManager;
}
/**
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 85a9d60..a704ec8 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -192,6 +192,7 @@ final class FragmentManagerImpl implements FragmentManager {
Activity mActivity;
boolean mNeedMenuInvalidate;
+ boolean mStateSaved;
// Temporary vars for state save and restore.
Bundle mStateBundle = null;
@@ -484,6 +485,7 @@ final class FragmentManagerImpl implements FragmentManager {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onDetach()");
}
+ f.mImmediateActivity = null;
f.mActivity = null;
}
}
@@ -678,6 +680,10 @@ final class FragmentManagerImpl implements FragmentManager {
}
public void enqueueAction(Runnable action) {
+ if (mStateSaved) {
+ throw new IllegalStateException(
+ "Can not perform this action after onSaveInstanceState");
+ }
synchronized (this) {
if (mPendingActions == null) {
mPendingActions = new ArrayList<Runnable>();
@@ -888,6 +894,8 @@ final class FragmentManagerImpl implements FragmentManager {
}
Parcelable saveAllState() {
+ mStateSaved = true;
+
if (mActive == null || mActive.size() <= 0) {
return null;
}
@@ -1029,6 +1037,22 @@ final class FragmentManagerImpl implements FragmentManager {
}
}
+ // Update the target of all retained fragments.
+ if (nonConfig != null) {
+ for (int i=0; i<nonConfig.size(); i++) {
+ Fragment f = nonConfig.get(i);
+ if (f.mTarget != null) {
+ if (f.mTarget.mIndex < mActive.size()) {
+ f.mTarget = mActive.get(f.mTarget.mIndex);
+ } else {
+ Log.w(TAG, "Re-attaching retained fragment " + f
+ + " target no longer exists: " + f.mTarget);
+ f.mTarget = null;
+ }
+ }
+ }
+ }
+
// Build the list of currently added fragments.
if (fms.mAdded != null) {
mAdded = new ArrayList<Fragment>(fms.mAdded.length);
@@ -1070,18 +1094,22 @@ final class FragmentManagerImpl implements FragmentManager {
}
public void dispatchCreate() {
+ mStateSaved = false;
moveToState(Fragment.CREATED, false);
}
public void dispatchActivityCreated() {
+ mStateSaved = false;
moveToState(Fragment.ACTIVITY_CREATED, false);
}
public void dispatchStart() {
+ mStateSaved = false;
moveToState(Fragment.STARTED, false);
}
public void dispatchResume() {
+ mStateSaved = false;
moveToState(Fragment.RESUMED, false);
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index c28ccd3..2efb09d 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -180,8 +180,8 @@ public abstract class PreferenceActivity extends ListActivity implements
*/
private static final int FIRST_REQUEST_CODE = 100;
- private static final int MSG_BIND_PREFERENCES = 0;
- private static final int MSG_BUILD_HEADERS = 1;
+ private static final int MSG_BIND_PREFERENCES = 1;
+ private static final int MSG_BUILD_HEADERS = 2;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index 0b5dffe..479497a 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -106,7 +106,7 @@ public abstract class PreferenceFragment extends Fragment implements
*/
private static final int FIRST_REQUEST_CODE = 100;
- private static final int MSG_BIND_PREFERENCES = 0;
+ private static final int MSG_BIND_PREFERENCES = 1;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {