From b2852cab467ef0c1181a1d5096c43c29fdf6a875 Mon Sep 17 00:00:00 2001 From: Jason Monk Date: Mon, 9 Jan 2017 15:12:37 -0500 Subject: [PATCH] Allow FragmentContainer to play a role in fragment construction This allows class swapping, dependency injection, and other fun stuff. Test: manual Change-Id: I93e17ccf9cebb6f542903d31597b5ea41544e069 --- api/current.txt | 1 + api/system-current.txt | 1 + api/test-current.txt | 1 + core/java/android/app/Fragment.java | 10 +++++++--- core/java/android/app/FragmentContainer.java | 11 +++++++++++ core/java/android/app/FragmentManager.java | 4 ++-- 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/api/current.txt b/api/current.txt index a8cdd10772b1d..8f47601187f67 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4586,6 +4586,7 @@ package android.app { public abstract class FragmentContainer { ctor public FragmentContainer(); + method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle); method public abstract android.view.View onFindViewById(int); method public abstract boolean onHasView(); } diff --git a/api/system-current.txt b/api/system-current.txt index cc1832d6ec68f..9cd632e0018ed 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -4742,6 +4742,7 @@ package android.app { public abstract class FragmentContainer { ctor public FragmentContainer(); + method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle); method public abstract android.view.View onFindViewById(int); method public abstract boolean onHasView(); } diff --git a/api/test-current.txt b/api/test-current.txt index e6148835639fe..3a4f211c88fe9 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4596,6 +4596,7 @@ package android.app { public abstract class FragmentContainer { ctor public FragmentContainer(); + method public android.app.Fragment instantiate(android.content.Context, java.lang.String, android.os.Bundle); method public abstract android.view.View onFindViewById(int); method public abstract boolean onHasView(); } diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 10ab2bc715904..62d68981d23c8 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -102,15 +102,19 @@ final class FragmentState implements Parcelable { mSavedFragmentState = in.readBundle(); } - public Fragment instantiate(FragmentHostCallback host, Fragment parent, - FragmentManagerNonConfig childNonConfig) { + public Fragment instantiate(FragmentHostCallback host, FragmentContainer container, + Fragment parent, FragmentManagerNonConfig childNonConfig) { if (mInstance == null) { final Context context = host.getContext(); if (mArguments != null) { mArguments.setClassLoader(context.getClassLoader()); } - mInstance = Fragment.instantiate(context, mClassName, mArguments); + if (container != null) { + mInstance = container.instantiate(context, mClassName, mArguments); + } else { + mInstance = Fragment.instantiate(context, mClassName, mArguments); + } if (mSavedFragmentState != null) { mSavedFragmentState.setClassLoader(context.getClassLoader()); diff --git a/core/java/android/app/FragmentContainer.java b/core/java/android/app/FragmentContainer.java index b2e0300b4016a..6ed54dcdbc855 100644 --- a/core/java/android/app/FragmentContainer.java +++ b/core/java/android/app/FragmentContainer.java @@ -18,6 +18,8 @@ package android.app; import android.annotation.IdRes; import android.annotation.Nullable; +import android.content.Context; +import android.os.Bundle; import android.view.View; /** @@ -35,4 +37,13 @@ public abstract class FragmentContainer { * Return {@code true} if the container holds any view. */ public abstract boolean onHasView(); + + /** + * Creates an instance of the specified fragment, can be overridden to construct fragments + * with dependencies, or change the fragment being constructed. By default just calls + * {@link Fragment#instantiate(Context, String, Bundle)}. + */ + public Fragment instantiate(Context context, String className, Bundle arguments) { + return Fragment.instantiate(context, className, arguments); + } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 92ba4408b5cef..95c0d0bb99687 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -2622,7 +2622,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate if (childNonConfigs != null && i < childNonConfigs.size()) { childNonConfig = childNonConfigs.get(i); } - Fragment f = fs.instantiate(mHost, mParent, childNonConfig); + Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig); if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f); mActive.add(f); // Now that the fragment is instantiated (or came from being @@ -3241,7 +3241,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate + Integer.toHexString(id) + " fname=" + fname + " existing=" + fragment); if (fragment == null) { - fragment = Fragment.instantiate(context, fname); + fragment = mContainer.instantiate(context, fname, null); fragment.mFromLayout = true; fragment.mFragmentId = id != 0 ? id : containerId; fragment.mContainerId = containerId;