Remove dependency upon FragmentActivity
The FragmentManagerImpl is intimately tied with a FragmentActivity. In
many cases, we want to be able to create / manage Fragments outside of
a FragmentManager. This defines a FragmentController interface that can
be used by any class to host Fragments.
Bug: 19569096
Change-Id: I62dee733a70577d0d3c8f96a89e4b05a3d5e18b0
diff --git a/.gitignore b/.gitignore
index 08a55c0..dbc32d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,7 @@
+.classpath
.gradle
+.project
+.settings/
+project.properties
+**/bin
+**/gen
diff --git a/v4/AndroidManifest.xml b/v4/AndroidManifest.xml
index 08dbb61..a21d926 100644
--- a/v4/AndroidManifest.xml
+++ b/v4/AndroidManifest.xml
@@ -15,5 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.support.v4">
+ <uses-sdk android:minSdkVersion="4"/>
<application />
</manifest>
diff --git a/v4/api/current.txt b/v4/api/current.txt
index 02321a3..3d7df08 100644
--- a/v4/api/current.txt
+++ b/v4/api/current.txt
@@ -114,6 +114,7 @@
method public boolean getAllowReturnTransitionOverlap();
method public final android.os.Bundle getArguments();
method public final android.support.v4.app.FragmentManager getChildFragmentManager();
+ method public final android.content.Context getContext();
method public java.lang.Object getEnterTransition();
method public java.lang.Object getExitTransition();
method public final android.support.v4.app.FragmentManager getFragmentManager();
@@ -146,7 +147,8 @@
method public final boolean isVisible();
method public void onActivityCreated(android.os.Bundle);
method public void onActivityResult(int, int, android.content.Intent);
- method public void onAttach(android.app.Activity);
+ method public void onAttach(android.content.Context);
+ method public deprecated void onAttach(android.app.Activity);
method public void onConfigurationChanged(android.content.res.Configuration);
method public boolean onContextItemSelected(android.view.MenuItem);
method public void onCreate(android.os.Bundle);
@@ -159,7 +161,8 @@
method public void onDestroyView();
method public void onDetach();
method public void onHiddenChanged(boolean);
- method public void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
+ method public void onInflate(android.content.Context, android.util.AttributeSet, android.os.Bundle);
+ method public deprecated void onInflate(android.app.Activity, android.util.AttributeSet, android.os.Bundle);
method public void onLowMemory();
method public boolean onOptionsItemSelected(android.view.MenuItem);
method public void onOptionsMenuClosed(android.view.Menu);
@@ -212,7 +215,7 @@
method public void onAttachFragment(android.support.v4.app.Fragment);
method protected void onResumeFragments();
method public java.lang.Object onRetainCustomNonConfigurationInstance();
- method public final java.lang.Object onRetainNonConfigurationInstance();
+ method public final deprecated java.lang.Object onRetainNonConfigurationInstance();
method public void setEnterSharedElementCallback(android.support.v4.app.SharedElementCallback);
method public void setExitSharedElementCallback(android.support.v4.app.SharedElementCallback);
method public void startActivityFromFragment(android.support.v4.app.Fragment, android.content.Intent, int);
@@ -222,6 +225,59 @@
method public void supportStartPostponedEnterTransition();
}
+ public abstract class FragmentContainer {
+ ctor public FragmentContainer();
+ method public abstract android.view.View findViewById(int);
+ method public abstract boolean hasView();
+ }
+
+ public class FragmentController {
+ method public void attachHost(android.support.v4.app.Fragment);
+ method public static final android.support.v4.app.FragmentController createController(android.support.v4.app.FragmentHostCallbacks);
+ method public void dispatchActivityCreated();
+ method public void dispatchConfigurationChanged(android.content.res.Configuration);
+ method public boolean dispatchContextItemSelected(android.view.MenuItem);
+ method public void dispatchCreate();
+ method public boolean dispatchCreateOptionsMenu(android.view.Menu, android.view.MenuInflater);
+ method public void dispatchDestroy();
+ method public void dispatchDestroyView();
+ method public void dispatchLowMemory();
+ method public boolean dispatchOptionsItemSelected(android.view.MenuItem);
+ method public void dispatchOptionsMenuClosed(android.view.Menu);
+ method public void dispatchPause();
+ method public boolean dispatchPrepareOptionsMenu(android.view.Menu);
+ method public void dispatchReallyStop();
+ method public void dispatchResume();
+ method public void dispatchStart();
+ method public void dispatchStop();
+ method public void dumpLoaders(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method public boolean execPendingActions();
+ method public java.util.List<android.support.v4.app.Fragment> getActiveFragments(java.util.List<android.support.v4.app.Fragment>);
+ method public int getActiveFragmentsCount();
+ method public android.support.v4.app.FragmentManager getSupportFragmentManager();
+ method public android.support.v4.app.LoaderManager getSupportLoaderManager();
+ method public void noteStateNotSaved();
+ method public android.view.View onCreateView(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet);
+ method public void restoreAllState(android.os.Parcelable, java.util.ArrayList<android.support.v4.app.Fragment>);
+ method public void restoreLoaderNonConfig(android.support.v4.util.SimpleArrayMap<java.lang.String, android.support.v4.app.LoaderManager>);
+ method public android.support.v4.util.SimpleArrayMap<java.lang.String, android.support.v4.app.LoaderManager> retainLoaderNonConfig();
+ method public java.util.ArrayList<android.support.v4.app.Fragment> retainNonConfig();
+ method public android.os.Parcelable saveAllState();
+ }
+
+ public class FragmentHostCallbacks extends android.support.v4.app.FragmentContainer {
+ ctor public FragmentHostCallbacks(android.content.Context, android.os.Handler, int);
+ method public void dump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
+ method public android.view.View findViewById(int);
+ method public android.view.LayoutInflater getLayoutInflater();
+ method public int getWindowAnimations();
+ method public boolean hasView();
+ method public boolean hasWindowAnimations();
+ method public boolean shouldSaveFragmentState(android.support.v4.app.Fragment);
+ method public void startActivityFromFragment(android.support.v4.app.Fragment, android.content.Intent, int);
+ method public void supportInvalidateOptionsMenu();
+ }
+
public abstract class FragmentManager {
ctor public FragmentManager();
method public abstract void addOnBackStackChangedListener(android.support.v4.app.FragmentManager.OnBackStackChangedListener);
diff --git a/v4/java/android/support/v4/app/BackStackRecord.java b/v4/java/android/support/v4/app/BackStackRecord.java
index 25f3ebf..32847ec 100644
--- a/v4/java/android/support/v4/app/BackStackRecord.java
+++ b/v4/java/android/support/v4/app/BackStackRecord.java
@@ -16,12 +16,10 @@
package android.support.v4.app;
-import android.graphics.Rect;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.util.LogWriter;
-import android.support.v4.util.Pair;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
import android.util.Log;
@@ -33,7 +31,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collection;
final class BackStackState implements Parcelable {
final int[] mOps;
@@ -48,7 +45,7 @@
final ArrayList<String> mSharedElementSourceNames;
final ArrayList<String> mSharedElementTargetNames;
- public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) {
+ public BackStackState(BackStackRecord bse) {
int numRemoved = 0;
BackStackRecord.Op op = bse.mHead;
while (op != null) {
@@ -371,14 +368,14 @@
public CharSequence getBreadCrumbTitle() {
if (mBreadCrumbTitleRes != 0) {
- return mManager.mActivity.getText(mBreadCrumbTitleRes);
+ return mManager.mHost.getContext().getText(mBreadCrumbTitleRes);
}
return mBreadCrumbTitleText;
}
public CharSequence getBreadCrumbShortTitle() {
if (mBreadCrumbShortTitleRes != 0) {
- return mManager.mActivity.getText(mBreadCrumbShortTitleRes);
+ return mManager.mHost.getContext().getText(mBreadCrumbShortTitleRes);
}
return mBreadCrumbShortTitleText;
}
@@ -1023,7 +1020,7 @@
// Adding a non-existent target view makes sure that the transitions don't target
// any views by default. They'll only target the views we tell add. If we don't
// add any, then no views will be targeted.
- state.nonExistentView = new View(mManager.mActivity);
+ state.nonExistentView = new View(mManager.mHost.getContext());
boolean anyTransitionStarted = false;
// Go over all leaving fragments.
diff --git a/v4/java/android/support/v4/app/DialogFragment.java b/v4/java/android/support/v4/app/DialogFragment.java
index 343c145..996d19f 100644
--- a/v4/java/android/support/v4/app/DialogFragment.java
+++ b/v4/java/android/support/v4/app/DialogFragment.java
@@ -320,7 +320,7 @@
return (LayoutInflater) mDialog.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
- return (LayoutInflater) mActivity.getSystemService(
+ return (LayoutInflater) mHost.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
diff --git a/v4/java/android/support/v4/app/Fragment.java b/v4/java/android/support/v4/app/Fragment.java
index eb6ab0d..2187777 100644
--- a/v4/java/android/support/v4/app/Fragment.java
+++ b/v4/java/android/support/v4/app/Fragment.java
@@ -22,8 +22,6 @@
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -89,20 +87,21 @@
mArguments = in.readBundle();
mSavedFragmentState = in.readBundle();
}
-
- public Fragment instantiate(FragmentActivity activity, Fragment parent) {
+
+ public Fragment instantiate(FragmentHostCallbacks host, Fragment parent) {
if (mInstance != null) {
return mInstance;
}
-
+
+ final Context context = host.getContext();
if (mArguments != null) {
- mArguments.setClassLoader(activity.getClassLoader());
+ mArguments.setClassLoader(context.getClassLoader());
}
-
- mInstance = Fragment.instantiate(activity, mClassName, mArguments);
-
+
+ mInstance = Fragment.instantiate(context, mClassName, mArguments);
+
if (mSavedFragmentState != null) {
- mSavedFragmentState.setClassLoader(activity.getClassLoader());
+ mSavedFragmentState.setClassLoader(context.getClassLoader());
mInstance.mSavedFragmentState = mSavedFragmentState;
}
mInstance.setIndex(mIndex, parent);
@@ -113,14 +112,14 @@
mInstance.mTag = mTag;
mInstance.mRetainInstance = mRetainInstance;
mInstance.mDetached = mDetached;
- mInstance.mFragmentManager = activity.mFragments;
+ mInstance.mFragmentManager = host.mFragmentManager;
if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
"Instantiated fragment " + mInstance);
return mInstance;
}
-
+
public int describeContents() {
return 0;
}
@@ -228,17 +227,17 @@
// True if this fragment has been restored from previously saved state.
boolean mRestored;
-
+
// 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.
FragmentManagerImpl mFragmentManager;
- // Activity this fragment is attached to.
- FragmentActivity mActivity;
+ // Host this fragment is attached to.
+ FragmentHostCallbacks mHost;
// Private fragment manager for child fragments inside of this one.
FragmentManagerImpl mChildFragmentManager;
@@ -348,10 +347,12 @@
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
+ @Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in, null);
}
+ @Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
@@ -606,22 +607,31 @@
}
/**
- * Return the Activity this fragment is currently associated with.
+ * Return the {@link Context} this fragment is currently associated with.
+ */
+ final public Context getContext() {
+ return mHost == null ? null : mHost.getContext();
+ }
+
+ /**
+ * Return the {@link FragmentActivity} this fragment is currently associated with.
+ * May return {@code null} if the fragment is associated with a {@link Context}
+ * instead.
*/
final public FragmentActivity getActivity() {
- return mActivity;
+ return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}
-
+
/**
* Return <code>getActivity().getResources()</code>.
*/
final public Resources getResources() {
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
- return mActivity.getResources();
+ return mHost.getContext().getResources();
}
-
+
/**
* Return a localized, styled CharSequence from the application's package's
* default string table.
@@ -701,7 +711,7 @@
* Return true if the fragment is currently added to its activity.
*/
final public boolean isAdded() {
- return mActivity != null && mAdded;
+ return mHost != null && mAdded;
}
/**
@@ -812,14 +822,14 @@
* Report that this fragment would like to participate in populating
* the options menu by receiving a call to {@link #onCreateOptionsMenu}
* and related methods.
- *
+ *
* @param hasMenu If true, the fragment has menu items to contribute.
*/
public void setHasOptionsMenu(boolean hasMenu) {
if (mHasMenu != hasMenu) {
mHasMenu = hasMenu;
if (isAdded() && !isHidden()) {
- mActivity.supportInvalidateOptionsMenu();
+ mHost.supportInvalidateOptionsMenu();
}
}
}
@@ -837,7 +847,7 @@
if (mMenuVisible != menuVisible) {
mMenuVisible = menuVisible;
if (mHasMenu && isAdded() && !isHidden()) {
- mActivity.supportInvalidateOptionsMenu();
+ mHost.supportInvalidateOptionsMenu();
}
}
}
@@ -878,42 +888,42 @@
if (mLoaderManager != null) {
return mLoaderManager;
}
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
mCheckedForLoaderManager = true;
- mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, true);
+ mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, true);
return mLoaderManager;
}
-
+
/**
* Call {@link Activity#startActivity(Intent)} on the fragment's
* containing Activity.
*/
public void startActivity(Intent intent) {
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
- mActivity.startActivityFromFragment(this, intent, -1);
+ mHost.startActivityFromFragment(this /*fragment*/, intent, -1);
}
-
+
/**
* Call {@link Activity#startActivityForResult(Intent, int)} on the fragment's
* containing Activity.
*/
public void startActivityForResult(Intent intent, int requestCode) {
- if (mActivity == null) {
+ if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
- mActivity.startActivityFromFragment(this, intent, requestCode);
+ mHost.startActivityFromFragment(this /*fragment*/, intent, requestCode);
}
-
+
/**
* Receive the result from a previous call to
* {@link #startActivityForResult(Intent, int)}. This follows the
* related Activity API as described there in
* {@link Activity#onActivityResult(int, int, Intent)}.
- *
+ *
* @param requestCode The integer request code originally supplied to
* startActivityForResult(), allowing you to identify who this
* result came from.
@@ -924,19 +934,19 @@
*/
public void onActivityResult(int requestCode, int resultCode, Intent data) {
}
-
+
/**
* @hide Hack so that DialogFragment can make its Dialog before creating
* its views, and the view construction can use the dialog's context for
* inflation. Maybe this should become a public API. Note sure.
*/
public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
- LayoutInflater result = mActivity.getLayoutInflater().cloneInContext(mActivity);
+ LayoutInflater result = mHost.getLayoutInflater();
getChildFragmentManager(); // Init if needed; use raw implementation below.
LayoutInflaterCompat.setFactory(result, mChildFragmentManager.getLayoutInflaterFactory());
return result;
}
-
+
/**
* Called when a fragment is being created as part of a view layout
* inflation, typically from setting the content view of an activity. This
@@ -973,31 +983,61 @@
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentArguments.java
* create}
*
- * @param activity The Activity that is inflating this fragment.
+ * @param context The Activity that is inflating this fragment.
* @param attrs The attributes at the tag where the fragment is
* being created.
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
+ public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
+ mCalled = true;
+ final Activity hostActivity = mHost == null ? null : mHost.getActivity();
+ if (hostActivity != null) {
+ mCalled = false;
+ onInflate(hostActivity, attrs, savedInstanceState);
+ }
+ }
+
+ /**
+ * Called when a fragment is being created as part of a view layout
+ * inflation, typically from setting the content view of an activity.
+ * <p>Deprecated. See {@link #onInflate(Context, AttributeSet, Bundle)}.
+ */
+ @Deprecated
public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
mCalled = true;
}
/**
- * Called when a fragment is first attached to its activity.
+ * Called when a fragment is first attached to its context.
* {@link #onCreate(Bundle)} will be called after this.
*/
+ public void onAttach(Context context) {
+ mCalled = true;
+ final Activity hostActivity = mHost == null ? null : mHost.getActivity();
+ if (hostActivity != null) {
+ mCalled = false;
+ onAttach(hostActivity);
+ }
+ }
+
+ /**
+ * Called when a fragment is first attached to its activity.
+ * {@link #onCreate(Bundle)} will be called after this.
+ * <p>Deprecated. See {@link #onAttach(Context)}.
+ */
+ @Deprecated
public void onAttach(Activity activity) {
mCalled = true;
}
-
+
/**
* Called when a fragment loads an animation.
*/
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
return null;
}
-
+
/**
* Called to do initial creation of a fragment. This is called after
* {@link #onAttach(Activity)} and before
@@ -1104,19 +1144,19 @@
*/
public void onStart() {
mCalled = true;
-
+
if (!mLoadersStarted) {
mLoadersStarted = true;
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
- mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+ mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
mLoaderManager.doStart();
}
}
}
-
+
/**
* Called when the fragment is visible to the user and actively running.
* This is generally
@@ -1198,7 +1238,7 @@
// + " mLoaderManager=" + mLoaderManager);
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
- mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+ mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
mLoaderManager.doDestroy();
@@ -1223,7 +1263,7 @@
mBackStackNesting = 0;
mFragmentManager = null;
mChildFragmentManager = null;
- mActivity = null;
+ mHost = null;
mFragmentId = 0;
mContainerId = 0;
mTag = null;
@@ -1335,6 +1375,7 @@
* It is not safe to hold onto the context menu after this method returns.
* {@inheritDoc}
*/
+ @Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
getActivity().onCreateContextMenu(menu, v, menuInfo);
}
@@ -1678,9 +1719,9 @@
writer.print(prefix); writer.print("mFragmentManager=");
writer.println(mFragmentManager);
}
- if (mActivity != null) {
- writer.print(prefix); writer.print("mActivity=");
- writer.println(mActivity);
+ if (mHost != null) {
+ writer.print(prefix); writer.print("mHost=");
+ writer.println(mHost);
}
if (mParentFragment != null) {
writer.print(prefix); writer.print("mParentFragment=");
@@ -1741,7 +1782,7 @@
void instantiateChildFragmentManager() {
mChildFragmentManager = new FragmentManagerImpl();
- mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() {
+ mChildFragmentManager.attachController(mHost, new FragmentContainer() {
@Override
@Nullable
public View findViewById(int id) {
@@ -1974,10 +2015,10 @@
mLoadersStarted = false;
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
- mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
+ mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
- if (!mActivity.mRetaining) {
+ if (!mRetaining) {
mLoaderManager.doStop();
} else {
mLoaderManager.doRetain();
diff --git a/v4/java/android/support/v4/app/FragmentActivity.java b/v4/java/android/support/v4/app/FragmentActivity.java
index 566ffed..f58f41b 100644
--- a/v4/java/android/support/v4/app/FragmentActivity.java
+++ b/v4/java/android/support/v4/app/FragmentActivity.java
@@ -31,6 +31,7 @@
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -40,6 +41,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
/**
* Base class for activities that want to use the support-based
@@ -75,9 +77,9 @@
*/
public class FragmentActivity extends Activity {
private static final String TAG = "FragmentActivity";
-
+
static final String FRAGMENTS_TAG = "android:support:fragments";
-
+
// This is the SDK API version of Honeycomb (3.0).
private static final int HONEYCOMB = 11;
@@ -103,21 +105,8 @@
}
};
- final FragmentManagerImpl mFragments = new FragmentManagerImpl();
- final FragmentContainer mContainer = new FragmentContainer() {
- @Override
- @Nullable
- public View findViewById(int id) {
- return FragmentActivity.this.findViewById(id);
- }
+ final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
- @Override
- public boolean hasView() {
- Window window = FragmentActivity.this.getWindow();
- return (window != null && window.peekDecorView() != null);
- }
- };
-
boolean mCreated;
boolean mResumed;
boolean mStopped;
@@ -126,23 +115,16 @@
boolean mOptionsMenuInvalidated;
- boolean mCheckedForLoaderManager;
- boolean mLoadersStarted;
- SimpleArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;
- LoaderManagerImpl mLoaderManager;
-
static final class NonConfigurationInstances {
- Object activity;
Object custom;
- SimpleArrayMap<String, Object> children;
ArrayList<Fragment> fragments;
- SimpleArrayMap<String, LoaderManagerImpl> loaders;
+ SimpleArrayMap<String, LoaderManager> loaders;
}
-
+
// ------------------------------------------------------------------------
// HOOKS INTO ACTIVITY
// ------------------------------------------------------------------------
-
+
/**
* Dispatch incoming result to the correct fragment.
*/
@@ -152,12 +134,15 @@
int index = requestCode>>16;
if (index != 0) {
index--;
- if (mFragments.mActive == null || index < 0 || index >= mFragments.mActive.size()) {
+ final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
+ if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount) {
Log.w(TAG, "Activity result fragment index out of range: 0x"
+ Integer.toHexString(requestCode));
return;
}
- Fragment frag = mFragments.mActive.get(index);
+ final List<Fragment> activeFragments =
+ mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
+ Fragment frag = activeFragments.get(index);
if (frag == null) {
Log.w(TAG, "Activity result no fragment exists for index: 0x"
+ Integer.toHexString(requestCode));
@@ -166,7 +151,7 @@
}
return;
}
-
+
super.onActivityResult(requestCode, resultCode, data);
}
@@ -175,7 +160,7 @@
* as appropriate.
*/
public void onBackPressed() {
- if (!mFragments.popBackStackImmediate()) {
+ if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
supportFinishAfterTransition();
}
}
@@ -246,20 +231,21 @@
/**
* Perform initialization of all fragments and loaders.
*/
+ @SuppressWarnings("deprecation")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
- mFragments.attachActivity(this, mContainer, null);
+ mFragments.attachHost(null /*parent*/);
// Old versions of the platform didn't do this!
if (getLayoutInflater().getFactory() == null) {
getLayoutInflater().setFactory(this);
}
-
+
super.onCreate(savedInstanceState);
-
- NonConfigurationInstances nc = (NonConfigurationInstances)
- getLastNonConfigurationInstance();
+
+ NonConfigurationInstances nc =
+ (NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
- mAllLoaderManagers = nc.loaders;
+ mFragments.restoreLoaderNonConfig(nc.loaders);
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
@@ -286,7 +272,7 @@
}
return super.onCreatePanelMenu(featureId, menu);
}
-
+
/**
* Add support for inflating the <fragment> tag.
*/
@@ -314,9 +300,7 @@
doReallyStop(false);
mFragments.dispatchDestroy();
- if (mLoaderManager != null) {
- mLoaderManager.doDestroy();
- }
+ mFragments.doLoaderDestroy();
}
/**
@@ -476,7 +460,9 @@
* Retain all appropriate fragment and loader state. You can NOT
* override this yourself! Use {@link #onRetainCustomNonConfigurationInstance()}
* if you want to retain your own state.
+ * @deprecated
*/
+ @Deprecated
@Override
public final Object onRetainNonConfigurationInstance() {
if (mStopped) {
@@ -486,35 +472,16 @@
Object custom = onRetainCustomNonConfigurationInstance();
ArrayList<Fragment> fragments = mFragments.retainNonConfig();
- boolean retainLoaders = false;
- if (mAllLoaderManagers != null) {
- // prune out any loader managers that were already stopped and so
- // have nothing useful to retain.
- final int N = mAllLoaderManagers.size();
- LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
- for (int i=N-1; i>=0; i--) {
- loaders[i] = mAllLoaderManagers.valueAt(i);
- }
- for (int i=0; i<N; i++) {
- LoaderManagerImpl lm = loaders[i];
- if (lm.mRetaining) {
- retainLoaders = true;
- } else {
- lm.doDestroy();
- mAllLoaderManagers.remove(lm.mWho);
- }
- }
- }
- if (fragments == null && !retainLoaders && custom == null) {
+ SimpleArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
+
+ if (fragments == null && loaders == null && custom == null) {
return null;
}
-
+
NonConfigurationInstances nci = new NonConfigurationInstances();
- nci.activity = null;
nci.custom = custom;
- nci.children = null;
nci.fragments = fragments;
- nci.loaders = mAllLoaderManagers;
+ nci.loaders = loaders;
return nci;
}
@@ -549,35 +516,13 @@
mFragments.noteStateNotSaved();
mFragments.execPendingActions();
-
- if (!mLoadersStarted) {
- mLoadersStarted = true;
- if (mLoaderManager != null) {
- mLoaderManager.doStart();
- } else if (!mCheckedForLoaderManager) {
- mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
- // the returned loader manager may be a new one, so we have to start it
- if ((mLoaderManager != null) && (!mLoaderManager.mStarted)) {
- mLoaderManager.doStart();
- }
- }
- mCheckedForLoaderManager = true;
- }
+
+ mFragments.doLoaderStart();
+
// NOTE: HC onStart goes here.
-
+
mFragments.dispatchStart();
- if (mAllLoaderManagers != null) {
- final int N = mAllLoaderManagers.size();
- LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
- for (int i=N-1; i>=0; i--) {
- loaders[i] = mAllLoaderManagers.valueAt(i);
- }
- for (int i=0; i<N; i++) {
- LoaderManagerImpl lm = loaders[i];
- lm.finishRetain();
- lm.doReportStart();
- }
- }
+ mFragments.reportLoaderStart();
}
/**
@@ -589,14 +534,14 @@
mStopped = true;
mHandler.sendEmptyMessage(MSG_REALLY_STOPPED);
-
+
mFragments.dispatchStop();
}
// ------------------------------------------------------------------------
// NEW METHODS
// ------------------------------------------------------------------------
-
+
/**
* Use this instead of {@link #onRetainNonConfigurationInstance()}.
* Retrieve later with {@link #getLastCustomNonConfigurationInstance()}.
@@ -609,6 +554,7 @@
* Return the value previously returned from
* {@link #onRetainCustomNonConfigurationInstance()}.
*/
+ @SuppressWarnings("deprecation")
public Object getLastCustomNonConfigurationInstance() {
NonConfigurationInstances nc = (NonConfigurationInstances)
getLastNonConfigurationInstance();
@@ -659,15 +605,8 @@
writer.print(mResumed); writer.print(" mStopped=");
writer.print(mStopped); writer.print(" mReallyStopped=");
writer.println(mReallyStopped);
- writer.print(innerPrefix); writer.print("mLoadersStarted=");
- writer.println(mLoadersStarted);
- if (mLoaderManager != null) {
- writer.print(prefix); writer.print("Loader Manager ");
- writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
- writer.println(":");
- mLoaderManager.dump(prefix + " ", fd, writer, args);
- }
- mFragments.dump(prefix, fd, writer, args);
+ mFragments.dumpLoaders(innerPrefix, fd, writer, args);
+ mFragments.getSupportFragmentManager().dump(prefix, fd, writer, args);
writer.print(prefix); writer.println("View Hierarchy:");
dumpViewHierarchy(prefix + " ", writer, getWindow().getDecorView());
}
@@ -776,16 +715,7 @@
* tell us what we need to know.
*/
void onReallyStop() {
- if (mLoadersStarted) {
- mLoadersStarted = false;
- if (mLoaderManager != null) {
- if (!mRetaining) {
- mLoaderManager.doStop();
- } else {
- mLoaderManager.doRetain();
- }
- }
- }
+ mFragments.doLoaderStop(mRetaining);
mFragments.dispatchReallyStop();
}
@@ -793,19 +723,24 @@
// ------------------------------------------------------------------------
// FRAGMENT SUPPORT
// ------------------------------------------------------------------------
-
+
/**
* Called when a fragment is attached to the activity.
*/
+ @SuppressWarnings("unused")
public void onAttachFragment(Fragment fragment) {
}
-
+
/**
* Return the FragmentManager for interacting with fragments associated
* with this activity.
*/
public FragmentManager getSupportFragmentManager() {
- return mFragments;
+ return mFragments.getSupportFragmentManager();
+ }
+
+ public LoaderManager getSupportLoaderManager() {
+ return mFragments.getSupportLoaderManager();
}
/**
@@ -823,7 +758,7 @@
/**
* Called by Fragment.startActivityForResult() to implement its behavior.
*/
- public void startActivityFromFragment(Fragment fragment, Intent intent,
+ public void startActivityFromFragment(Fragment fragment, Intent intent,
int requestCode) {
if (requestCode == -1) {
super.startActivityForResult(intent, -1);
@@ -834,47 +769,58 @@
}
super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));
}
-
- void invalidateSupportFragment(String who) {
- //Log.v(TAG, "invalidateSupportFragment: who=" + who);
- if (mAllLoaderManagers != null) {
- LoaderManagerImpl lm = mAllLoaderManagers.get(who);
- if (lm != null && !lm.mRetaining) {
- lm.doDestroy();
- mAllLoaderManagers.remove(who);
- }
+
+ class HostCallbacks extends FragmentHostCallbacks {
+ public HostCallbacks() {
+ super(FragmentActivity.this /*fragmentActivity*/);
}
- }
-
- // ------------------------------------------------------------------------
- // LOADER SUPPORT
- // ------------------------------------------------------------------------
-
- /**
- * Return the LoaderManager for this fragment, creating it if needed.
- */
- public LoaderManager getSupportLoaderManager() {
- if (mLoaderManager != null) {
- return mLoaderManager;
+
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ FragmentActivity.this.dump(prefix, fd, writer, args);
}
- mCheckedForLoaderManager = true;
- mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);
- return mLoaderManager;
- }
-
- LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
- if (mAllLoaderManagers == null) {
- mAllLoaderManagers = new SimpleArrayMap<String, LoaderManagerImpl>();
+
+ @Override
+ public boolean shouldSaveFragmentState(Fragment fragment) {
+ return !isFinishing();
}
- LoaderManagerImpl lm = mAllLoaderManagers.get(who);
- if (lm == null) {
- if (create) {
- lm = new LoaderManagerImpl(who, this, started);
- mAllLoaderManagers.put(who, lm);
- }
- } else {
- lm.updateActivity(this);
+
+ @Override
+ public LayoutInflater getLayoutInflater() {
+ return FragmentActivity.this.getLayoutInflater().cloneInContext(FragmentActivity.this);
}
- return lm;
+
+ @Override
+ public void supportInvalidateOptionsMenu() {
+ FragmentActivity.this.supportInvalidateOptionsMenu();
+ }
+
+ @Override
+ public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {
+ FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode);
+ }
+
+ @Override
+ public boolean hasWindowAnimations() {
+ return getWindow() != null;
+ }
+
+ @Override
+ public int getWindowAnimations() {
+ final Window w = getWindow();
+ return (w == null) ? 0 : w.getAttributes().windowAnimations;
+ }
+
+ @Nullable
+ @Override
+ public View findViewById(int id) {
+ return FragmentActivity.this.findViewById(id);
+ }
+
+ @Override
+ public boolean hasView() {
+ final Window w = getWindow();
+ return (w != null && w.peekDecorView() != null);
+ }
}
}
diff --git a/v4/java/android/support/v4/app/FragmentContainer.java b/v4/java/android/support/v4/app/FragmentContainer.java
new file mode 100644
index 0000000..74cd7cc
--- /dev/null
+++ b/v4/java/android/support/v4/app/FragmentContainer.java
@@ -0,0 +1,23 @@
+package android.support.v4.app;
+
+import android.support.annotation.IdRes;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+
+/**
+ * Callbacks to a {@link Fragment}'s container.
+ */
+public abstract class FragmentContainer {
+ /**
+ * Return the view with the given resource ID. May return {@code null} if the
+ * view is not a child of this container.
+ */
+ @Nullable
+ public abstract View findViewById(@IdRes int id);
+
+ /**
+ * Return {@code true} if the container holds any view.
+ */
+ public abstract boolean hasView();
+}
diff --git a/v4/java/android/support/v4/app/FragmentController.java b/v4/java/android/support/v4/app/FragmentController.java
new file mode 100644
index 0000000..bd2da21
--- /dev/null
+++ b/v4/java/android/support/v4/app/FragmentController.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.app;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Parcelable;
+import android.support.v4.util.SimpleArrayMap;
+import android.util.AttributeSet;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides integration points with a {@link FragmentManager}. For example, a fragment
+ * host, such as {@link FragmentActivity}, uses the {@link FragmentController} to control
+ * the {@link Fragment} lifecycle.
+ */
+public class FragmentController {
+ private final FragmentHostCallbacks mHost;
+
+ /**
+ * Returns a {@link FragmentController}.
+ */
+ public static final FragmentController createController(FragmentHostCallbacks callbacks) {
+ return new FragmentController(callbacks);
+ }
+
+ private FragmentController(FragmentHostCallbacks callbacks) {
+ mHost = callbacks;
+ }
+
+ public FragmentManager getSupportFragmentManager() {
+ return mHost.getFragmentManagerImpl();
+ }
+
+ public LoaderManager getSupportLoaderManager() {
+ return mHost.getLoaderManagerImpl();
+ }
+
+ /** Returns the number of active fragments. */
+ public int getActiveFragmentsCount() {
+ final List<Fragment> actives = mHost.mFragmentManager.mActive;
+ return actives == null ? 0 : actives.size();
+ }
+
+ /** Returns the list of active fragments. */
+ public List<Fragment> getActiveFragments(List<Fragment> actives) {
+ if (mHost.mFragmentManager.mActive == null) {
+ return null;
+ }
+ if (actives == null) {
+ actives = new ArrayList<Fragment>(getActiveFragmentsCount());
+ }
+ actives.addAll(mHost.mFragmentManager.mActive);
+ return actives;
+ }
+
+ /** Attaches the host to the FragmentManager. */
+ public void attachHost(Fragment parent) {
+ mHost.mFragmentManager.attachController(
+ mHost, mHost /*container*/, parent);
+ }
+
+ public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+ return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
+ }
+
+ /**
+ * Marks the fragment state as unsaved. This allows for "state loss" detection.
+ */
+ public void noteStateNotSaved() {
+ mHost.mFragmentManager.noteStateNotSaved();
+ }
+
+ /**
+ * Saves the state for all Fragments.
+ */
+ public Parcelable saveAllState() {
+ return mHost.mFragmentManager.saveAllState();
+ }
+
+ /**
+ * Restores the saved state for all Fragments. The given Fragment list are Fragment
+ * instances retained across configuration changes.
+ *
+ * @see #retainNonConfig()
+ */
+ public void restoreAllState(Parcelable state, ArrayList<Fragment> nonConfigList) {
+ mHost.mFragmentManager.restoreAllState(state, nonConfigList);
+ }
+
+ /**
+ * Returns a list of Fragments that have opted to retain their instance across
+ * configuration changes.
+ */
+ public ArrayList<Fragment> retainNonConfig() {
+ return mHost.mFragmentManager.retainNonConfig();
+ }
+
+ public void dispatchCreate() {
+ mHost.mFragmentManager.dispatchCreate();
+ }
+
+ public void dispatchActivityCreated() {
+ mHost.mFragmentManager.dispatchActivityCreated();
+ }
+
+ public void dispatchStart() {
+ mHost.mFragmentManager.dispatchStart();
+ }
+
+ public void dispatchResume() {
+ mHost.mFragmentManager.dispatchResume();
+ }
+
+ public void dispatchPause() {
+ mHost.mFragmentManager.dispatchPause();
+ }
+
+ public void dispatchStop() {
+ mHost.mFragmentManager.dispatchStop();
+ }
+
+ public void dispatchReallyStop() {
+ mHost.mFragmentManager.dispatchReallyStop();
+ }
+
+ public void dispatchDestroyView() {
+ mHost.mFragmentManager.dispatchDestroyView();
+ }
+
+ public void dispatchDestroy() {
+ mHost.mFragmentManager.dispatchDestroy();
+ }
+
+ public void dispatchConfigurationChanged(Configuration newConfig) {
+ mHost.mFragmentManager.dispatchConfigurationChanged(newConfig);
+ }
+
+ public void dispatchLowMemory() {
+ mHost.mFragmentManager.dispatchLowMemory();
+ }
+
+ public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ return mHost.mFragmentManager.dispatchCreateOptionsMenu(menu, inflater);
+ }
+
+ public boolean dispatchPrepareOptionsMenu(Menu menu) {
+ return mHost.mFragmentManager.dispatchPrepareOptionsMenu(menu);
+ }
+
+ public boolean dispatchOptionsItemSelected(MenuItem item) {
+ return mHost.mFragmentManager.dispatchOptionsItemSelected(item);
+ }
+
+ public boolean dispatchContextItemSelected(MenuItem item) {
+ return mHost.mFragmentManager.dispatchContextItemSelected(item);
+ }
+
+ public void dispatchOptionsMenuClosed(Menu menu) {
+ mHost.mFragmentManager.dispatchOptionsMenuClosed(menu);
+ }
+
+ public boolean execPendingActions() {
+ return mHost.mFragmentManager.execPendingActions();
+ }
+
+ void doLoaderStart() {
+ mHost.doLoaderStart();
+ }
+
+ /**
+ * Stops the loaders, optionally retaining their state. This is useful for keeping the
+ * loader state across configuration changes.
+ *
+ * @param retain When {@code true}, the loaders aren't stopped, but, their instances
+ * are retained in a started state
+ */
+ void doLoaderStop(boolean retain) {
+ mHost.doLoaderStop(retain);
+ }
+
+ void doLoaderRetain() {
+ mHost.doLoaderRetain();
+ }
+
+ void doLoaderDestroy() {
+ mHost.doLoaderDestroy();
+ }
+
+ void reportLoaderStart() {
+ mHost.reportLoaderStart();
+ }
+
+ /**
+ * Returns a list of LoaderManagers that have opted to retain their instance across
+ * configuration changes.
+ */
+ public SimpleArrayMap<String, LoaderManager> retainLoaderNonConfig() {
+ return mHost.retainLoaderNonConfig();
+ }
+
+ /**
+ * Restores the saved state for all LoaderManagers. The given LoaderManager list are
+ * LoaderManager instances retained across configuration changes.
+ *
+ * @see #retainLoaderNonConfig()
+ */
+ public void restoreLoaderNonConfig(SimpleArrayMap<String, LoaderManager> loaderManagers) {
+ mHost.restoreLoaderNonConfig(loaderManagers);
+ }
+
+ public void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ mHost.dumpLoaders(prefix, fd, writer, args);
+ }
+}
diff --git a/v4/java/android/support/v4/app/FragmentHostCallbacks.java b/v4/java/android/support/v4/app/FragmentHostCallbacks.java
new file mode 100644
index 0000000..9b42a96
--- /dev/null
+++ b/v4/java/android/support/v4/app/FragmentHostCallbacks.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.app;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.Nullable;
+import android.support.v4.util.SimpleArrayMap;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Provides integration points with the host that is managing the {@link Fragment} lifecycle.
+ */
+public class FragmentHostCallbacks extends FragmentContainer {
+ private final Activity mActivity;
+ final Context mContext;
+ private final Handler mHandler;
+ final int mWindowAnimations;
+ final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
+ private SimpleArrayMap<String, LoaderManager> mAllLoaderManagers;
+ private LoaderManagerImpl mLoaderManager;
+ private boolean mCheckedForLoaderManager;
+ private boolean mLoadersStarted;
+
+ public FragmentHostCallbacks(Context context, Handler handler, int windowAnimations) {
+ this(null /*activity*/, context, handler, windowAnimations);
+ }
+
+ FragmentHostCallbacks(FragmentActivity activity) {
+ this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
+ }
+
+ FragmentHostCallbacks(Activity activity, Context context, Handler handler,
+ int windowAnimations) {
+ mActivity = activity;
+ mContext = context;
+ mHandler = handler;
+ mWindowAnimations = windowAnimations;
+ }
+
+ /**
+ * Print internal state into the given stream.
+ *
+ * @param prefix Desired prefix to prepend at each line of output.
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param writer The PrintWriter to which you should dump your state. This will be closed
+ * for you after you return.
+ * @param args additional arguments to the dump request.
+ */
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ }
+
+ /**
+ * Return {@code true} if the fragment's state needs to be saved.
+ */
+ public boolean shouldSaveFragmentState(Fragment fragment) {
+ return true;
+ }
+
+ /**
+ * Return a {@link LayoutInflater}.
+ * See {@link Activity#getLayoutInflater()}.
+ */
+ public LayoutInflater getLayoutInflater() {
+ return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ /**
+ * Invalidates the activity's options menu.
+ * See {@link FragmentActivity#supportInvalidateOptionsMenu()}
+ */
+ public void supportInvalidateOptionsMenu() {
+ }
+
+ /**
+ * Starts a new {@link Activity} from the given fragment.
+ * See {@link FragmentActivity#startActivityForResult(Intent, int)}.
+ */
+ public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {
+ if (requestCode != -1) {
+ throw new IllegalStateException(
+ "Starting activity with a requestCode requires a FragmentActivity host");
+ }
+ mContext.startActivity(intent);
+ }
+
+ /**
+ * Return {@code true} if there are window animations.
+ */
+ public boolean hasWindowAnimations() {
+ return true;
+ }
+
+ /**
+ * Return the window animations.
+ */
+ public int getWindowAnimations() {
+ return mWindowAnimations;
+ }
+
+ @Nullable
+ @Override
+ public View findViewById(int id) {
+ return null;
+ }
+
+ @Override
+ public boolean hasView() {
+ return true;
+ }
+
+ Activity getActivity() {
+ return mActivity;
+ }
+
+ Context getContext() {
+ return mContext;
+ }
+
+ Handler getHandler() {
+ return mHandler;
+ }
+
+ FragmentManagerImpl getFragmentManagerImpl() {
+ return mFragmentManager;
+ }
+
+ LoaderManagerImpl getLoaderManagerImpl() {
+ if (mLoaderManager != null) {
+ return mLoaderManager;
+ }
+ mCheckedForLoaderManager = true;
+ mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true /*create*/);
+ return mLoaderManager;
+ }
+
+ void inactivateFragment(String who) {
+ //Log.v(TAG, "invalidateSupportFragment: who=" + who);
+ if (mAllLoaderManagers != null) {
+ LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
+ if (lm != null && !lm.mRetaining) {
+ lm.doDestroy();
+ mAllLoaderManagers.remove(who);
+ }
+ }
+ }
+
+ void onFragmentInflate(Fragment fragment, AttributeSet attrs, Bundle savedInstanceState) {
+ fragment.onInflate(mContext, attrs, savedInstanceState);
+ }
+
+ void onFragmentAttach(Fragment fragment) {
+ fragment.onAttach(mContext);
+ }
+
+ void doLoaderStart() {
+ if (mLoadersStarted) {
+ return;
+ }
+ mLoadersStarted = true;
+
+ if (mLoaderManager != null) {
+ mLoaderManager.doStart();
+ } else if (!mCheckedForLoaderManager) {
+ mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
+ // the returned loader manager may be a new one, so we have to start it
+ if ((mLoaderManager != null) && (!mLoaderManager.mStarted)) {
+ mLoaderManager.doStart();
+ }
+ }
+ mCheckedForLoaderManager = true;
+ }
+
+ // retain -- whether to stop the loader or retain it
+ void doLoaderStop(boolean retain) {
+ if (mLoaderManager == null) {
+ return;
+ }
+
+ if (!mLoadersStarted) {
+ return;
+ }
+ mLoadersStarted = false;
+
+ if (retain) {
+ mLoaderManager.doRetain();
+ } else {
+ mLoaderManager.doStop();
+ }
+ }
+
+ void doLoaderRetain() {
+ if (mLoaderManager == null) {
+ return;
+ }
+ mLoaderManager.doRetain();
+ }
+
+ void doLoaderDestroy() {
+ if (mLoaderManager == null) {
+ return;
+ }
+ mLoaderManager.doDestroy();
+ }
+
+ void reportLoaderStart() {
+ if (mAllLoaderManagers != null) {
+ final int N = mAllLoaderManagers.size();
+ LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
+ for (int i=N-1; i>=0; i--) {
+ loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
+ }
+ for (int i=0; i<N; i++) {
+ LoaderManagerImpl lm = loaders[i];
+ lm.finishRetain();
+ lm.doReportStart();
+ }
+ }
+ }
+
+ LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
+ if (mAllLoaderManagers == null) {
+ mAllLoaderManagers = new SimpleArrayMap<String, LoaderManager>();
+ }
+ LoaderManagerImpl lm = (LoaderManagerImpl) mAllLoaderManagers.get(who);
+ if (lm == null) {
+ if (create) {
+ lm = new LoaderManagerImpl(who, this, started);
+ mAllLoaderManagers.put(who, lm);
+ }
+ } else {
+ lm.updateHostController(this);
+ }
+ return lm;
+ }
+
+ SimpleArrayMap<String, LoaderManager> retainLoaderNonConfig() {
+ boolean retainLoaders = false;
+ if (mAllLoaderManagers != null) {
+ // prune out any loader managers that were already stopped and so
+ // have nothing useful to retain.
+ final int N = mAllLoaderManagers.size();
+ LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
+ for (int i=N-1; i>=0; i--) {
+ loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
+ }
+ for (int i=0; i<N; i++) {
+ LoaderManagerImpl lm = loaders[i];
+ if (lm.mRetaining) {
+ retainLoaders = true;
+ } else {
+ lm.doDestroy();
+ mAllLoaderManagers.remove(lm.mWho);
+ }
+ }
+ }
+
+ if (retainLoaders) {
+ return mAllLoaderManagers;
+ }
+ return null;
+ }
+
+ void restoreLoaderNonConfig(SimpleArrayMap<String, LoaderManager> loaderManagers) {
+ mAllLoaderManagers = loaderManagers;
+ }
+
+ void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ writer.print(prefix); writer.print("mLoadersStarted=");
+ writer.println(mLoadersStarted);
+ if (mLoaderManager != null) {
+ writer.print(prefix); writer.print("Loader Manager ");
+ writer.print(Integer.toHexString(System.identityHashCode(mLoaderManager)));
+ writer.println(":");
+ mLoaderManager.dump(prefix + " ", fd, writer, args);
+ }
+ }
+}
diff --git a/v4/java/android/support/v4/app/FragmentManager.java b/v4/java/android/support/v4/app/FragmentManager.java
index 6d41d45..5739057 100644
--- a/v4/java/android/support/v4/app/FragmentManager.java
+++ b/v4/java/android/support/v4/app/FragmentManager.java
@@ -26,7 +26,6 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.IdRes;
-import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.util.DebugUtils;
import android.support.v4.util.LogWriter;
@@ -399,15 +398,6 @@
}
/**
- * Callbacks from FragmentManagerImpl to its container.
- */
-interface FragmentContainer {
- @Nullable
- public View findViewById(@IdRes int id);
- public boolean hasView();
-}
-
-/**
* Container for fragments associated with an activity.
*/
final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory {
@@ -438,7 +428,8 @@
ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
int mCurState = Fragment.INITIALIZING;
- FragmentActivity mActivity;
+ FragmentHostCallbacks mHost;
+ FragmentController mController;
FragmentContainer mContainer;
Fragment mParent;
@@ -464,9 +455,9 @@
Log.e(TAG, "Activity state:");
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
- if (mActivity != null) {
+ if (mHost != null) {
try {
- mActivity.dump(" ", null, pw, new String[] { });
+ mHost.dump(" ", null, pw, new String[] { });
} catch (Exception e) {
Log.e(TAG, "Failed dumping state", e);
}
@@ -494,7 +485,7 @@
public void popBackStack() {
enqueueAction(new Runnable() {
@Override public void run() {
- popBackStackState(mActivity.mHandler, null, -1, 0);
+ popBackStackState(mHost.getHandler(), null, -1, 0);
}
}, false);
}
@@ -503,14 +494,14 @@
public boolean popBackStackImmediate() {
checkStateLoss();
executePendingTransactions();
- return popBackStackState(mActivity.mHandler, null, -1, 0);
+ return popBackStackState(mHost.getHandler(), null, -1, 0);
}
@Override
public void popBackStack(final String name, final int flags) {
enqueueAction(new Runnable() {
@Override public void run() {
- popBackStackState(mActivity.mHandler, name, -1, flags);
+ popBackStackState(mHost.getHandler(), name, -1, flags);
}
}, false);
}
@@ -519,7 +510,7 @@
public boolean popBackStackImmediate(String name, int flags) {
checkStateLoss();
executePendingTransactions();
- return popBackStackState(mActivity.mHandler, name, -1, flags);
+ return popBackStackState(mHost.getHandler(), name, -1, flags);
}
@Override
@@ -529,7 +520,7 @@
}
enqueueAction(new Runnable() {
@Override public void run() {
- popBackStackState(mActivity.mHandler, null, id, flags);
+ popBackStackState(mHost.getHandler(), null, id, flags);
}
}, false);
}
@@ -541,7 +532,7 @@
if (id < 0) {
throw new IllegalArgumentException("Bad id: " + id);
}
- return popBackStackState(mActivity.mHandler, null, id, flags);
+ return popBackStackState(mHost.getHandler(), null, id, flags);
}
@Override
@@ -628,7 +619,7 @@
if (mParent != null) {
DebugUtils.buildShortClassTag(mParent, sb);
} else {
- DebugUtils.buildShortClassTag(mActivity, sb);
+ DebugUtils.buildShortClassTag(mHost, sb);
}
sb.append("}}");
return sb.toString();
@@ -725,7 +716,7 @@
}
writer.print(prefix); writer.println("FragmentManager misc state:");
- writer.print(prefix); writer.print(" mActivity="); writer.println(mActivity);
+ writer.print(prefix); writer.print(" mHost="); writer.println(mHost);
writer.print(prefix); writer.print(" mContainer="); writer.println(mContainer);
if (mParent != null) {
writer.print(prefix); writer.print(" mParent="); writer.println(mParent);
@@ -785,7 +776,7 @@
}
if (fragment.mNextAnim != 0) {
- Animation anim = AnimationUtils.loadAnimation(mActivity, fragment.mNextAnim);
+ Animation anim = AnimationUtils.loadAnimation(mHost.getContext(), fragment.mNextAnim);
if (anim != null) {
return anim;
}
@@ -802,21 +793,21 @@
switch (styleIndex) {
case ANIM_STYLE_OPEN_ENTER:
- return makeOpenCloseAnimation(mActivity, 1.125f, 1.0f, 0, 1);
+ return makeOpenCloseAnimation(mHost.getContext(), 1.125f, 1.0f, 0, 1);
case ANIM_STYLE_OPEN_EXIT:
- return makeOpenCloseAnimation(mActivity, 1.0f, .975f, 1, 0);
+ return makeOpenCloseAnimation(mHost.getContext(), 1.0f, .975f, 1, 0);
case ANIM_STYLE_CLOSE_ENTER:
- return makeOpenCloseAnimation(mActivity, .975f, 1.0f, 0, 1);
+ return makeOpenCloseAnimation(mHost.getContext(), .975f, 1.0f, 0, 1);
case ANIM_STYLE_CLOSE_EXIT:
- return makeOpenCloseAnimation(mActivity, 1.0f, 1.075f, 1, 0);
+ return makeOpenCloseAnimation(mHost.getContext(), 1.0f, 1.075f, 1, 0);
case ANIM_STYLE_FADE_ENTER:
- return makeFadeAnimation(mActivity, 0, 1);
+ return makeFadeAnimation(mHost.getContext(), 0, 1);
case ANIM_STYLE_FADE_EXIT:
- return makeFadeAnimation(mActivity, 1, 0);
+ return makeFadeAnimation(mHost.getContext(), 1, 0);
}
- if (transitionStyle == 0 && mActivity.getWindow() != null) {
- transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
+ if (transitionStyle == 0 && mHost.hasWindowAnimations()) {
+ transitionStyle = mHost.getWindowAnimations();
}
if (transitionStyle == 0) {
return null;
@@ -881,7 +872,7 @@
case Fragment.INITIALIZING:
if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
if (f.mSavedFragmentState != null) {
- f.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
+ f.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
f.mTarget = getFragment(f.mSavedFragmentState,
@@ -899,18 +890,18 @@
}
}
}
- f.mActivity = mActivity;
+ f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
- ? mParent.mChildFragmentManager : mActivity.mFragments;
+ ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
f.mCalled = false;
- f.onAttach(mActivity);
+ mHost.onFragmentAttach(f);
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onAttach()");
}
if (f.mParentFragment == null) {
- mActivity.onAttachFragment(f);
+ mHost.onFragmentAttach(f);
}
if (!f.mRetaining) {
@@ -1021,7 +1012,7 @@
if (f.mView != null) {
// Need to save the current view state if not
// done already.
- if (!mActivity.isFinishing() && f.mSavedViewState == null) {
+ if (mHost.shouldSaveFragmentState(f) && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
@@ -1098,7 +1089,7 @@
if (!f.mRetaining) {
makeInactive(f);
} else {
- f.mActivity = null;
+ f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
f.mChildFragmentManager = null;
@@ -1121,8 +1112,8 @@
}
void moveToState(int newState, int transit, int transitStyle, boolean always) {
- if (mActivity == null && newState != Fragment.INITIALIZING) {
- throw new IllegalStateException("No activity");
+ if (mHost == null && newState != Fragment.INITIALIZING) {
+ throw new IllegalStateException("No host");
}
if (!always && mCurState == newState) {
@@ -1146,8 +1137,8 @@
startPendingDeferredFragments();
}
- if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
- mActivity.supportInvalidateOptionsMenu();
+ if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
+ mHost.supportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
@@ -1194,7 +1185,7 @@
mAvailIndices = new ArrayList<Integer>();
}
mAvailIndices.add(f.mIndex);
- mActivity.invalidateSupportFragment(f.mWho);
+ mHost.inactivateFragment(f.mWho);
f.initState();
}
@@ -1395,7 +1386,7 @@
checkStateLoss();
}
synchronized (this) {
- if (mDestroyed || mActivity == null) {
+ if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
@@ -1403,8 +1394,8 @@
}
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
- mActivity.mHandler.removeCallbacks(mExecCommit);
- mActivity.mHandler.post(mExecCommit);
+ mHost.getHandler().removeCallbacks(mExecCommit);
+ mHost.getHandler().post(mExecCommit);
}
}
}
@@ -1473,7 +1464,7 @@
throw new IllegalStateException("Recursive entry to executePendingTransactions");
}
- if (Looper.myLooper() != mActivity.mHandler.getLooper()) {
+ if (Looper.myLooper() != mHost.getHandler().getLooper()) {
throw new IllegalStateException("Must be called from main thread of process");
}
@@ -1493,7 +1484,7 @@
}
mPendingActions.toArray(mTmpActions);
mPendingActions.clear();
- mActivity.mHandler.removeCallbacks(mExecCommit);
+ mHost.getHandler().removeCallbacks(mExecCommit);
}
mExecutingActions = true;
@@ -1537,6 +1528,7 @@
reportBackStackChanged();
}
+ @SuppressWarnings("unused")
boolean popBackStackState(Handler handler, String name, int id, int flags) {
if (mBackStack == null) {
return false;
@@ -1780,7 +1772,7 @@
if (N > 0) {
backStack = new BackStackState[N];
for (int i=0; i<N; i++) {
- backStack[i] = new BackStackState(this, mBackStack.get(i));
+ backStack[i] = new BackStackState(mBackStack.get(i));
if (DEBUG) Log.v(TAG, "saveAllState: adding back stack #" + i
+ ": " + mBackStack.get(i));
}
@@ -1815,7 +1807,7 @@
f.mAdded = false;
f.mTarget = null;
if (fs.mSavedFragmentState != null) {
- fs.mSavedFragmentState.setClassLoader(mActivity.getClassLoader());
+ fs.mSavedFragmentState.setClassLoader(mHost.getContext().getClassLoader());
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG);
f.mSavedFragmentState = fs.mSavedFragmentState;
@@ -1832,7 +1824,7 @@
for (int i=0; i<fms.mActive.length; i++) {
FragmentState fs = fms.mActive[i];
if (fs != null) {
- Fragment f = fs.instantiate(mActivity, mParent);
+ Fragment f = fs.instantiate(mHost, mParent);
if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
mActive.add(f);
// Now that the fragment is instantiated (or came from being
@@ -1906,11 +1898,11 @@
mBackStack = null;
}
}
-
- public void attachActivity(FragmentActivity activity,
+
+ public void attachController(FragmentHostCallbacks host,
FragmentContainer container, Fragment parent) {
- if (mActivity != null) throw new IllegalStateException("Already attached");
- mActivity = activity;
+ if (mHost != null) throw new IllegalStateException("Already attached");
+ mHost = host;
mContainer = container;
mParent = parent;
}
@@ -1964,7 +1956,7 @@
mDestroyed = true;
execPendingActions();
moveToState(Fragment.INITIALIZING, false);
- mActivity = null;
+ mHost = null;
mContainer = null;
mParent = null;
}
@@ -2132,7 +2124,7 @@
String tag = a.getString(FragmentTag.Fragment_tag);
a.recycle();
- if (!Fragment.isSupportFragmentClass(mActivity, fname)) {
+ if (!Fragment.isSupportFragmentClass(mHost.getContext(), fname)) {
// Invalid support lib fragment; let the device's framework handle it.
// This will allow android.app.Fragments to do the right thing.
return null;
@@ -2166,7 +2158,7 @@
fragment.mTag = tag;
fragment.mInLayout = true;
fragment.mFragmentManager = this;
- fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+ mHost.onFragmentInflate(fragment, attrs, fragment.mSavedFragmentState);
addFragment(fragment, true);
} else if (fragment.mInLayout) {
@@ -2184,7 +2176,7 @@
// from last saved state), then give it the attributes to
// initialize itself.
if (!fragment.mRetaining) {
- fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+ mHost.onFragmentInflate(fragment, attrs, fragment.mSavedFragmentState);
}
}
diff --git a/v4/java/android/support/v4/app/LoaderManager.java b/v4/java/android/support/v4/app/LoaderManager.java
index e57d01c..e67cc4b 100644
--- a/v4/java/android/support/v4/app/LoaderManager.java
+++ b/v4/java/android/support/v4/app/LoaderManager.java
@@ -184,6 +184,9 @@
public boolean hasRunningLoaders() { return false; }
}
+/**
+ * @hide
+ */
class LoaderManagerImpl extends LoaderManager {
static final String TAG = "LoaderManager";
static boolean DEBUG = false;
@@ -201,12 +204,12 @@
final String mWho;
- FragmentActivity mActivity;
boolean mStarted;
boolean mRetaining;
boolean mRetainingStarted;
boolean mCreatingLoader;
+ private FragmentHostCallbacks mHost;
final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,
Loader.OnLoadCanceledListener<Object> {
@@ -217,8 +220,11 @@
boolean mHaveData;
boolean mDeliveredData;
Object mData;
+ @SuppressWarnings("hiding")
boolean mStarted;
+ @SuppressWarnings("hiding")
boolean mRetaining;
+ @SuppressWarnings("hiding")
boolean mRetainingStarted;
boolean mReportNextStart;
boolean mDestroyed;
@@ -343,15 +349,15 @@
if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
if (DEBUG) Log.v(TAG, " Reseting: " + this);
String lastBecause = null;
- if (mActivity != null) {
- lastBecause = mActivity.mFragments.mNoTransactionsBecause;
- mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset";
+ if (mHost != null) {
+ lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
+ mHost.mFragmentManager.mNoTransactionsBecause = "onLoaderReset";
}
try {
mCallbacks.onLoaderReset(mLoader);
} finally {
- if (mActivity != null) {
- mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+ if (mHost != null) {
+ mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
}
}
}
@@ -452,25 +458,25 @@
mInactiveLoaders.remove(mId);
}
- if (mActivity != null && !hasRunningLoaders()) {
- mActivity.mFragments.startPendingDeferredFragments();
+ if (mHost != null && !hasRunningLoaders()) {
+ mHost.mFragmentManager.startPendingDeferredFragments();
}
}
void callOnLoadFinished(Loader<Object> loader, Object data) {
if (mCallbacks != null) {
String lastBecause = null;
- if (mActivity != null) {
- lastBecause = mActivity.mFragments.mNoTransactionsBecause;
- mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
+ if (mHost != null) {
+ lastBecause = mHost.mFragmentManager.mNoTransactionsBecause;
+ mHost.mFragmentManager.mNoTransactionsBecause = "onLoadFinished";
}
try {
if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": "
+ loader.dataToString(data));
mCallbacks.onLoadFinished(loader, data);
} finally {
- if (mActivity != null) {
- mActivity.mFragments.mNoTransactionsBecause = lastBecause;
+ if (mHost != null) {
+ mHost.mFragmentManager.mNoTransactionsBecause = lastBecause;
}
}
mDeliveredData = true;
@@ -517,21 +523,21 @@
}
}
- LoaderManagerImpl(String who, FragmentActivity activity, boolean started) {
+ LoaderManagerImpl(String who, FragmentHostCallbacks host, boolean started) {
mWho = who;
- mActivity = activity;
+ mHost = host;
mStarted = started;
}
- void updateActivity(FragmentActivity activity) {
- mActivity = activity;
+ void updateHostController(FragmentHostCallbacks host) {
+ mHost = host;
}
private LoaderInfo createLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
- LoaderInfo info = new LoaderInfo(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
+ LoaderInfo info = new LoaderInfo(id, args, callback);
Loader<Object> loader = callback.onCreateLoader(id, args);
- info.mLoader = (Loader<Object>)loader;
+ info.mLoader = loader;
return info;
}
@@ -576,7 +582,7 @@
* @param id A unique (to this LoaderManager instance) identifier under
* which to manage the new Loader.
* @param args Optional arguments that will be propagated to
- * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
+ * {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
* @param callback Interface implementing management of this Loader. Required.
* Its onCreateLoader() method will be called while inside of the function to
* instantiate the Loader object.
@@ -626,7 +632,7 @@
* @param id A unique (to this LoaderManager instance) identifier under
* which to manage the new Loader.
* @param args Optional arguments that will be propagated to
- * {@link LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
+ * {@link android.support.v4.app.LoaderManager.LoaderCallbacks#onCreateLoader(int, Bundle) LoaderCallbacks.onCreateLoader()}.
* @param callback Interface implementing management of this Loader. Required.
* Its onCreateLoader() method will be called while inside of the function to
* instantiate the Loader object.
@@ -717,8 +723,8 @@
mInactiveLoaders.removeAt(idx);
info.destroy();
}
- if (mActivity != null && !hasRunningLoaders()) {
- mActivity.mFragments.startPendingDeferredFragments();
+ if (mHost != null && !hasRunningLoaders()) {
+ mHost.mFragmentManager.startPendingDeferredFragments();
}
}
@@ -836,7 +842,7 @@
sb.append("LoaderManager{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" in ");
- DebugUtils.buildShortClassTag(mActivity, sb);
+ DebugUtils.buildShortClassTag(mHost, sb);
sb.append("}}");
return sb.toString();
}