diff options
| -rw-r--r-- | core/java/android/app/Fragment.java | 18 | ||||
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 15 |
2 files changed, 33 insertions, 0 deletions
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 73b96f1ba169..612998dd5158 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -762,6 +762,24 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * are going to call back with {@link #onActivityResult(int, int, Intent)}. */ public void setTargetFragment(Fragment fragment, int requestCode) { + // Don't allow a caller to set a target fragment in another FragmentManager, + // but there's a snag: people do set target fragments before fragments get added. + // We'll have the FragmentManager check that for validity when we move + // the fragments to a valid state. + final FragmentManager mine = getFragmentManager(); + final FragmentManager theirs = fragment.getFragmentManager(); + if (mine != null && theirs != null && mine != theirs) { + throw new IllegalArgumentException("Fragment " + fragment + + " must share the same FragmentManager to be set as a target fragment"); + } + + // Don't let someone create a cycle. + for (Fragment check = fragment; check != null; check = check.getTargetFragment()) { + if (check == this) { + throw new IllegalArgumentException("Setting " + fragment + " as the target of " + + this + " would create a target cycle"); + } + } mTarget = fragment; mTargetRequestCode = requestCode; } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 44f1322f4b40..32cf1c341b4c 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1110,10 +1110,25 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } } } + f.mHost = mHost; f.mParentFragment = mParent; f.mFragmentManager = mParent != null ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl(); + + // If we have a target fragment, push it along to at least CREATED + // so that this one can rely on it as an initialized dependency. + if (f.mTarget != null) { + if (!mActive.contains(f.mTarget)) { + throw new IllegalStateException("Fragment " + f + + " declared target fragment " + f.mTarget + + " that does not belong to this FragmentManager!"); + } + if (f.mTarget.mState < Fragment.CREATED) { + moveToState(f.mTarget, Fragment.CREATED, 0, 0, true); + } + } + dispatchOnFragmentPreAttached(f, mHost.getContext(), false); f.mCalled = false; f.onAttach(mHost.getContext()); |