am c7e9a17a: am 10a54a79: Merge "Remove dependency upon FragmentActivity" into mnc-dev

* commit 'c7e9a17a626cc07eb9e4cb4b897dad50d3fb68a8':
  Remove dependency upon FragmentActivity
This commit is contained in:
Todd Kennedy
2015-04-30 21:10:06 +00:00
committed by Android Git Automerger
11 changed files with 1115 additions and 260 deletions

View File

@ -4328,9 +4328,11 @@ package android.app {
method public boolean getAllowReturnTransitionOverlap();
method public final android.os.Bundle getArguments();
method public final android.app.FragmentManager getChildFragmentManager();
method public android.content.Context getContext();
method public android.transition.Transition getEnterTransition();
method public android.transition.Transition getExitTransition();
method public final android.app.FragmentManager getFragmentManager();
method public final java.lang.Object getHost();
method public final int getId();
method public android.app.LoaderManager getLoaderManager();
method public final android.app.Fragment getParentFragment();
@ -4360,7 +4362,8 @@ package android.app {
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);
@ -4374,7 +4377,8 @@ package android.app {
method public void onDetach();
method public void onHiddenChanged(boolean);
method public deprecated void onInflate(android.util.AttributeSet, android.os.Bundle);
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);
@ -4441,6 +4445,64 @@ package android.app {
method public abstract boolean onBreadCrumbClick(android.app.FragmentManager.BackStackEntry, int);
}
public abstract class FragmentContainer {
ctor public FragmentContainer();
method public abstract android.view.View onFindViewById(int);
method public abstract boolean onHasView();
}
public class FragmentController {
method public void attachHost(android.app.Fragment);
method public static final android.app.FragmentController createController(android.app.FragmentHostCallback<?>);
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 dispatchResume();
method public void dispatchStart();
method public void dispatchStop();
method public void dispatchTrimMemory(int);
method public void doLoaderDestroy();
method public void doLoaderStart();
method public void doLoaderStop(boolean);
method public void dumpLoaders(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public boolean execPendingActions();
method public android.app.Fragment findFragmentByWho(java.lang.String);
method public android.app.FragmentManager getFragmentManager();
method public android.app.LoaderManager getLoaderManager();
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 reportLoaderStart();
method public void restoreAllState(android.os.Parcelable, java.util.List<android.app.Fragment>);
method public void restoreLoaderNonConfig(android.util.ArrayMap<java.lang.String, android.app.LoaderManager>);
method public android.util.ArrayMap<java.lang.String, android.app.LoaderManager> retainLoaderNonConfig();
method public java.util.List<android.app.Fragment> retainNonConfig();
method public android.os.Parcelable saveAllState();
}
public abstract class FragmentHostCallback extends android.app.FragmentContainer {
ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public android.view.View onFindViewById(int);
method public abstract E onGetHost();
method public android.view.LayoutInflater onGetLayoutInflater();
method public int onGetWindowAnimations();
method public boolean onHasView();
method public boolean onHasWindowAnimations();
method public void onInvalidateOptionsMenu();
method public boolean onShouldSaveFragmentState(android.app.Fragment);
method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
method public boolean onUseFragmentManagerInflaterFactory();
}
public abstract class FragmentManager {
ctor public FragmentManager();
method public abstract void addOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener);

View File

@ -4418,9 +4418,11 @@ package android.app {
method public boolean getAllowReturnTransitionOverlap();
method public final android.os.Bundle getArguments();
method public final android.app.FragmentManager getChildFragmentManager();
method public android.content.Context getContext();
method public android.transition.Transition getEnterTransition();
method public android.transition.Transition getExitTransition();
method public final android.app.FragmentManager getFragmentManager();
method public final java.lang.Object getHost();
method public final int getId();
method public android.app.LoaderManager getLoaderManager();
method public final android.app.Fragment getParentFragment();
@ -4450,7 +4452,8 @@ package android.app {
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);
@ -4464,7 +4467,8 @@ package android.app {
method public void onDetach();
method public void onHiddenChanged(boolean);
method public deprecated void onInflate(android.util.AttributeSet, android.os.Bundle);
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);
@ -4531,6 +4535,64 @@ package android.app {
method public abstract boolean onBreadCrumbClick(android.app.FragmentManager.BackStackEntry, int);
}
public abstract class FragmentContainer {
ctor public FragmentContainer();
method public abstract android.view.View onFindViewById(int);
method public abstract boolean onHasView();
}
public class FragmentController {
method public void attachHost(android.app.Fragment);
method public static final android.app.FragmentController createController(android.app.FragmentHostCallback<?>);
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 dispatchResume();
method public void dispatchStart();
method public void dispatchStop();
method public void dispatchTrimMemory(int);
method public void doLoaderDestroy();
method public void doLoaderStart();
method public void doLoaderStop(boolean);
method public void dumpLoaders(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public boolean execPendingActions();
method public android.app.Fragment findFragmentByWho(java.lang.String);
method public android.app.FragmentManager getFragmentManager();
method public android.app.LoaderManager getLoaderManager();
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 reportLoaderStart();
method public void restoreAllState(android.os.Parcelable, java.util.List<android.app.Fragment>);
method public void restoreLoaderNonConfig(android.util.ArrayMap<java.lang.String, android.app.LoaderManager>);
method public android.util.ArrayMap<java.lang.String, android.app.LoaderManager> retainLoaderNonConfig();
method public java.util.List<android.app.Fragment> retainNonConfig();
method public android.os.Parcelable saveAllState();
}
public abstract class FragmentHostCallback extends android.app.FragmentContainer {
ctor public FragmentHostCallback(android.content.Context, android.os.Handler, int);
method public void onDump(java.lang.String, java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
method public android.view.View onFindViewById(int);
method public abstract E onGetHost();
method public android.view.LayoutInflater onGetLayoutInflater();
method public int onGetWindowAnimations();
method public boolean onHasView();
method public boolean onHasWindowAnimations();
method public void onInvalidateOptionsMenu();
method public boolean onShouldSaveFragmentState(android.app.Fragment);
method public void onStartActivityFromFragment(android.app.Fragment, android.content.Intent, int, android.os.Bundle);
method public boolean onUseFragmentManagerInflaterFactory();
}
public abstract class FragmentManager {
ctor public FragmentManager();
method public abstract void addOnBackStackChangedListener(android.app.FragmentManager.OnBackStackChangedListener);

View File

@ -108,6 +108,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* An activity is a single, focused thing that the user can do. Almost all
@ -706,8 +707,6 @@ public class Activity extends ContextThemeWrapper
/*package*/ ActivityThread mMainThread;
Activity mParent;
boolean mCalled;
boolean mCheckedForLoaderManager;
boolean mLoadersStarted;
/*package*/ boolean mResumed;
private boolean mStopped;
boolean mFinished;
@ -726,8 +725,8 @@ public class Activity extends ContextThemeWrapper
static final class NonConfigurationInstances {
Object activity;
HashMap<String, Object> children;
ArrayList<Fragment> fragments;
ArrayMap<String, LoaderManagerImpl> loaders;
List<Fragment> fragments;
ArrayMap<String, LoaderManager> loaders;
VoiceInteractor voiceInteractor;
}
/* package */ NonConfigurationInstances mLastNonConfigurationInstances;
@ -747,26 +746,13 @@ public class Activity extends ContextThemeWrapper
private CharSequence mTitle;
private int mTitleColor = 0;
final FragmentManagerImpl mFragments = new FragmentManagerImpl();
final FragmentContainer mContainer = new FragmentContainer() {
@Override
@Nullable
public View findViewById(int id) {
return Activity.this.findViewById(id);
}
@Override
public boolean hasView() {
Window window = Activity.this.getWindow();
return (window != null && window.peekDecorView() != null);
}
};
// we must have a handler before the FragmentController is constructed
final Handler mHandler = new Handler();
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
// Most recent call to requestVisibleBehind().
boolean mVisibleBehind;
ArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;
LoaderManagerImpl mLoaderManager;
private static final class ManagedCursor {
ManagedCursor(Cursor cursor) {
mCursor = cursor;
@ -802,7 +788,6 @@ public class Activity extends ContextThemeWrapper
private final Object mInstanceTracker = StrictMode.trackActivity(this);
private Thread mUiThread;
final Handler mHandler = new Handler();
ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
@ -863,28 +848,7 @@ public class Activity extends ContextThemeWrapper
* Return the LoaderManager for this activity, creating it if needed.
*/
public LoaderManager getLoaderManager() {
if (mLoaderManager != null) {
return mLoaderManager;
}
mCheckedForLoaderManager = true;
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);
return mLoaderManager;
}
LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
if (mAllLoaderManagers == null) {
mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>();
}
LoaderManagerImpl lm = mAllLoaderManagers.get(who);
if (lm == null) {
if (create) {
lm = new LoaderManagerImpl(who, this, started);
mAllLoaderManagers.put(who, lm);
}
} else {
lm.updateActivity(this);
}
return lm;
return mFragments.getLoaderManager();
}
/**
@ -931,7 +895,7 @@ public class Activity extends ContextThemeWrapper
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
if (mLastNonConfigurationInstances != null) {
mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
}
if (mActivityInfo.parentActivityName != null) {
if (mActionBar == null) {
@ -1172,15 +1136,7 @@ public class Activity extends ContextThemeWrapper
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
mCalled = true;
if (!mLoadersStarted) {
mLoadersStarted = true;
if (mLoaderManager != null) {
mLoaderManager.doStart();
} else if (!mCheckedForLoaderManager) {
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
}
mCheckedForLoaderManager = true;
}
mFragments.doLoaderStart();
getApplication().dispatchActivityStarted(this);
}
@ -1873,27 +1829,9 @@ public class Activity extends ContextThemeWrapper
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
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 (activity == null && children == null && fragments == null && !retainLoaders
List<Fragment> fragments = mFragments.retainNonConfig();
ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
if (activity == null && children == null && fragments == null && loaders == null
&& mVoiceInteractor == null) {
return null;
}
@ -1902,7 +1840,7 @@ public class Activity extends ContextThemeWrapper
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
nci.loaders = mAllLoaderManagers;
nci.loaders = loaders;
nci.voiceInteractor = mVoiceInteractor;
return nci;
}
@ -1924,18 +1862,7 @@ public class Activity extends ContextThemeWrapper
* with this activity.
*/
public FragmentManager getFragmentManager() {
return mFragments;
}
void invalidateFragment(String who) {
//Log.v(TAG, "invalidateFragmentIndex: index=" + index);
if (mAllLoaderManagers != null) {
LoaderManagerImpl lm = mAllLoaderManagers.get(who);
if (lm != null && !lm.mRetaining) {
lm.doDestroy();
mAllLoaderManagers.remove(who);
}
}
return mFragments.getFragmentManager();
}
/**
@ -2518,7 +2445,7 @@ public class Activity extends ContextThemeWrapper
return;
}
if (!mFragments.popBackStackImmediate()) {
if (!mFragments.getFragmentManager().popBackStackImmediate()) {
finishAfterTransition();
}
}
@ -5518,21 +5445,13 @@ public class Activity extends ContextThemeWrapper
writer.print(mResumed); writer.print(" mStopped=");
writer.print(mStopped); writer.print(" mFinished=");
writer.println(mFinished);
writer.print(innerPrefix); writer.print("mLoadersStarted=");
writer.println(mLoadersStarted);
writer.print(innerPrefix); writer.print("mChangingConfigurations=");
writer.println(mChangingConfigurations);
writer.print(innerPrefix); writer.print("mCurrentConfig=");
writer.println(mCurrentConfig);
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.getFragmentManager().dump(innerPrefix, fd, writer, args);
if (getWindow() != null &&
getWindow().peekDecorView() != null &&
@ -6128,7 +6047,7 @@ public class Activity extends ContextThemeWrapper
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
attachBaseContext(context);
mFragments.attachActivity(this, mContainer, null);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this);
mWindow.setCallback(this);
@ -6211,18 +6130,7 @@ public class Activity extends ContextThemeWrapper
" did not call through to super.onStart()");
}
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();
mActivityTransitionState.enterReady(this);
}
@ -6328,16 +6236,7 @@ public class Activity extends ContextThemeWrapper
final void performStop() {
mDoReportFullyDrawn = false;
if (mLoadersStarted) {
mLoadersStarted = false;
if (mLoaderManager != null) {
if (!mChangingConfigurations) {
mLoaderManager.doStop();
} else {
mLoaderManager.doRetain();
}
}
}
mFragments.doLoaderStop(mChangingConfigurations /*retain*/);
if (!mStopped) {
if (mWindow != null) {
@ -6379,9 +6278,7 @@ public class Activity extends ContextThemeWrapper
mWindow.destroy();
mFragments.dispatchDestroy();
onDestroy();
if (mLoaderManager != null) {
mLoaderManager.doDestroy();
}
mFragments.doLoaderDestroy();
if (mVoiceInteractor != null) {
mVoiceInteractor.detachActivity();
}
@ -6541,4 +6438,74 @@ public class Activity extends ContextThemeWrapper
return intent != null
&& PackageManager.ACTION_REQUEST_PERMISSIONS.equals(intent.getAction());
}
class HostCallbacks extends FragmentHostCallback<Activity> {
public HostCallbacks() {
super(Activity.this /*activity*/);
}
@Override
public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
Activity.this.dump(prefix, fd, writer, args);
}
@Override
public boolean onShouldSaveFragmentState(Fragment fragment) {
return !isFinishing();
}
@Override
public LayoutInflater onGetLayoutInflater() {
final LayoutInflater result = Activity.this.getLayoutInflater();
if (onUseFragmentManagerInflaterFactory()) {
return result.cloneInContext(Activity.this);
}
return result;
}
@Override
public boolean onUseFragmentManagerInflaterFactory() {
// Newer platform versions use the child fragment manager's LayoutInflaterFactory.
return getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP;
}
@Override
public Activity onGetHost() {
return Activity.this;
}
@Override
public void onInvalidateOptionsMenu() {
Activity.this.invalidateOptionsMenu();
}
@Override
public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
Bundle options) {
Activity.this.startActivityFromFragment(fragment, intent, requestCode, options);
}
@Override
public boolean onHasWindowAnimations() {
return getWindow() != null;
}
@Override
public int onGetWindowAnimations() {
final Window w = getWindow();
return (w == null) ? 0 : w.getAttributes().windowAnimations;
}
@Nullable
@Override
public View onFindViewById(int id) {
return Activity.this.findViewById(id);
}
@Override
public boolean onHasView() {
final Window w = getWindow();
return (w != null && w.peekDecorView() != null);
}
}
}

View File

@ -416,14 +416,14 @@ final class BackStackRecord extends FragmentTransaction implements
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;
}
@ -868,7 +868,7 @@ final class BackStackRecord extends FragmentTransaction implements
*/
private void calculateFragments(SparseArray<Fragment> firstOutFragments,
SparseArray<Fragment> lastInFragments) {
if (!mManager.mContainer.hasView()) {
if (!mManager.mContainer.onHasView()) {
return; // nothing to see, so no transitions
}
Op op = mHead;
@ -926,7 +926,7 @@ final class BackStackRecord extends FragmentTransaction implements
*/
public void calculateBackFragments(SparseArray<Fragment> firstOutFragments,
SparseArray<Fragment> lastInFragments) {
if (!mManager.mContainer.hasView()) {
if (!mManager.mContainer.onHasView()) {
return; // nothing to see, so no transitions
}
Op op = mHead;
@ -1002,7 +1002,7 @@ final class BackStackRecord extends FragmentTransaction implements
// 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());
// Go over all leaving fragments.
for (int i = 0; i < firstOutFragments.size(); i++) {
@ -1275,7 +1275,7 @@ final class BackStackRecord extends FragmentTransaction implements
*/
private void configureTransitions(int containerId, TransitionState state, boolean isBack,
SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) {
ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.findViewById(containerId);
ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.onFindViewById(containerId);
if (sceneRoot != null) {
Fragment inFragment = lastInFragments.get(containerId);
Fragment outFragment = firstOutFragments.get(containerId);

View File

@ -410,7 +410,7 @@ public class DialogFragment extends Fragment
return (LayoutInflater)mDialog.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
return (LayoutInflater)mActivity.getSystemService(
return (LayoutInflater) mHost.getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}

View File

@ -26,7 +26,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;
@ -94,19 +93,20 @@ final class FragmentState implements Parcelable {
mSavedFragmentState = in.readBundle();
}
public Fragment instantiate(Activity activity, Fragment parent) {
public Fragment instantiate(FragmentHostCallback 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);
@ -117,7 +117,7 @@ final class FragmentState implements Parcelable {
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);
@ -425,7 +425,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
FragmentManagerImpl mFragmentManager;
// Activity this fragment is attached to.
Activity mActivity;
FragmentHostCallback mHost;
// Private fragment manager for child fragments inside of this one.
FragmentManagerImpl mChildFragmentManager;
@ -774,21 +774,37 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
return mTargetRequestCode;
}
/**
* Return the {@link Context} this fragment is currently associated with.
*/
public Context getContext() {
return mHost == null ? null : mHost.getContext();
}
/**
* Return the Activity this fragment is currently associated with.
*/
final public Activity getActivity() {
return mActivity;
return mHost == null ? null : mHost.getActivity();
}
/**
* Return the host object of this fragment. May return {@code null} if the fragment
* isn't currently being hosted.
*/
@Nullable
final public Object getHost() {
return mHost == null ? null : mHost.onGetHost();
}
/**
* 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();
}
/**
@ -870,7 +886,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* Return true if the fragment is currently added to its activity.
*/
final public boolean isAdded() {
return mActivity != null && mAdded;
return mHost != null && mAdded;
}
/**
@ -1037,11 +1053,11 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
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;
}
@ -1065,15 +1081,15 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* Context.startActivity(Intent, Bundle)} for more details.
*/
public void startActivity(Intent intent, Bundle options) {
if (mActivity == null) {
if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
if (options != null) {
mActivity.startActivityFromFragment(this, intent, -1, options);
mHost.onStartActivityFromFragment(this, intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
mActivity.startActivityFromFragment(this, intent, -1);
mHost.onStartActivityFromFragment(this, intent, -1, null /*options*/);
}
}
@ -1090,10 +1106,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* containing Activity.
*/
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
if (mActivity == null) {
if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
mActivity.startActivityFromFragment(this, intent, requestCode, options);
mHost.onStartActivityFromFragment(this, intent, requestCode, options);
}
/**
@ -1181,11 +1197,12 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* @see android.content.Context#checkSelfPermission(String)
*/
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
if (mActivity == null) {
if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
Intent intent = mActivity.getPackageManager().buildRequestPermissionsIntent(permissions);
mActivity.startActivityFromFragment(this, intent, requestCode, null);
Intent intent =
mHost.getContext().getPackageManager().buildRequestPermissionsIntent(permissions);
mHost.onStartActivityFromFragment(this, intent, requestCode, null);
}
/**
@ -1211,19 +1228,16 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* inflation. Maybe this should become a public API. Note sure.
*/
public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
// Newer platform versions use the child fragment manager's LayoutInflaterFactory.
if (mActivity.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
LayoutInflater result = mActivity.getLayoutInflater().cloneInContext(mActivity);
final LayoutInflater result = mHost.onGetLayoutInflater();
if (mHost.onUseFragmentManagerInflaterFactory()) {
getChildFragmentManager(); // Init if needed; use raw implementation below.
result.setPrivateFactory(mChildFragmentManager.getLayoutInflaterFactory());
return result;
} else {
return mActivity.getLayoutInflater();
}
return result;
}
/**
* @deprecated Use {@link #onInflate(Activity, AttributeSet, Bundle)} instead.
* @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead.
*/
@Deprecated
public void onInflate(AttributeSet attrs, Bundle savedInstanceState) {
@ -1266,29 +1280,29 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
* {@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 Context 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(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
onInflate(attrs, savedInstanceState);
mCalled = true;
TypedArray a = activity.obtainStyledAttributes(attrs,
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.Fragment);
mEnterTransition = loadTransition(activity, a, mEnterTransition, null,
mEnterTransition = loadTransition(context, a, mEnterTransition, null,
com.android.internal.R.styleable.Fragment_fragmentEnterTransition);
mReturnTransition = loadTransition(activity, a, mReturnTransition, USE_DEFAULT_TRANSITION,
mReturnTransition = loadTransition(context, a, mReturnTransition, USE_DEFAULT_TRANSITION,
com.android.internal.R.styleable.Fragment_fragmentReturnTransition);
mExitTransition = loadTransition(activity, a, mExitTransition, null,
mExitTransition = loadTransition(context, a, mExitTransition, null,
com.android.internal.R.styleable.Fragment_fragmentExitTransition);
mReenterTransition = loadTransition(activity, a, mReenterTransition, USE_DEFAULT_TRANSITION,
mReenterTransition = loadTransition(context, a, mReenterTransition, USE_DEFAULT_TRANSITION,
com.android.internal.R.styleable.Fragment_fragmentReenterTransition);
mSharedElementEnterTransition = loadTransition(activity, a, mSharedElementEnterTransition,
mSharedElementEnterTransition = loadTransition(context, a, mSharedElementEnterTransition,
null, com.android.internal.R.styleable.Fragment_fragmentSharedElementEnterTransition);
mSharedElementReturnTransition = loadTransition(activity, a, mSharedElementReturnTransition,
mSharedElementReturnTransition = loadTransition(context, a, mSharedElementReturnTransition,
USE_DEFAULT_TRANSITION,
com.android.internal.R.styleable.Fragment_fragmentSharedElementReturnTransition);
if (mAllowEnterTransitionOverlap == null) {
@ -1303,9 +1317,30 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
/**
* Called when a fragment is first attached to its activity.
* @deprecated Use {@link #onInflate(Context, AttributeSet, Bundle)} instead.
*/
@Deprecated
public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
mCalled = true;
}
/**
* 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);
}
}
/**
* @deprecated Use {@link #onAttach(Context)} instead.
*/
@Deprecated
public void onAttach(Activity activity) {
mCalled = true;
}
@ -1428,7 +1463,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
mLoadersStarted = true;
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
mLoaderManager.doStart();
@ -1521,7 +1556,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// + " mLoaderManager=" + mLoaderManager);
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
mLoaderManager.doDestroy();
@ -1546,7 +1581,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
mBackStackNesting = 0;
mFragmentManager = null;
mChildFragmentManager = null;
mActivity = null;
mHost = null;
mFragmentId = 0;
mContainerId = 0;
mTag = null;
@ -2034,9 +2069,9 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
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=");
@ -2094,10 +2129,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
void instantiateChildFragmentManager() {
mChildFragmentManager = new FragmentManagerImpl();
mChildFragmentManager.attachActivity(mActivity, new FragmentContainer() {
mChildFragmentManager.attachController(mHost, new FragmentContainer() {
@Override
@Nullable
public View findViewById(int id) {
public View onFindViewById(int id) {
if (mView == null) {
throw new IllegalStateException("Fragment does not have a view");
}
@ -2105,7 +2140,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
@Override
public boolean hasView() {
public boolean onHasView() {
return (mView != null);
}
}, this);
@ -2319,13 +2354,13 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
mLoadersStarted = false;
if (!mCheckedForLoaderManager) {
mCheckedForLoaderManager = true;
mLoaderManager = mActivity.getLoaderManager(mWho, mLoadersStarted, false);
mLoaderManager = mHost.getLoaderManager(mWho, mLoadersStarted, false);
}
if (mLoaderManager != null) {
if (mActivity == null || !mActivity.mChangingConfigurations) {
mLoaderManager.doStop();
} else {
if (mRetaining) {
mLoaderManager.doRetain();
} else {
mLoaderManager.doStop();
}
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.app;
import android.annotation.IdRes;
import android.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 onFindViewById(@IdRes int id);
/**
* Return {@code true} if the container holds any view.
*/
public abstract boolean onHasView();
}

View File

@ -0,0 +1,384 @@
/*
* 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.app;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.ArrayMap;
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.List;
/**
* Provides integration points with a {@link FragmentManager} for a fragment host.
* <p>
* It is the responsibility of the host to take care of the Fragment's lifecycle.
* The methods provided by {@link FragmentController} are for that purpose.
*/
public class FragmentController {
private final FragmentHostCallback<?> mHost;
/**
* Returns a {@link FragmentController}.
*/
public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback<?> callbacks) {
mHost = callbacks;
}
/**
* Returns a {@link FragmentManager} for this controller.
*/
public FragmentManager getFragmentManager() {
return mHost.getFragmentManagerImpl();
}
/**
* Returns a {@link LoaderManager}.
*/
public LoaderManager getLoaderManager() {
return mHost.getLoaderManagerImpl();
}
/**
* Returns a fragment with the given identifier.
*/
@Nullable
public Fragment findFragmentByWho(String who) {
return mHost.mFragmentManager.findFragmentByWho(who);
}
/**
* Attaches the host to the FragmentManager for this controller. The host must be
* attached before the FragmentManager can be used to manage Fragments.
* */
public void attachHost(Fragment parent) {
mHost.mFragmentManager.attachController(
mHost, mHost /*container*/, parent);
}
/**
* Instantiates a Fragment's view.
*
* @param parent The parent that the created view will be placed
* in; <em>note that this may be null</em>.
* @param name Tag name to be inflated.
* @param context The context the view is being created in.
* @param attrs Inflation attributes as specified in XML file.
*
* @return view the newly created view
*/
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, List<Fragment> nonConfigList) {
mHost.mFragmentManager.restoreAllState(state, nonConfigList);
}
/**
* Returns a list of Fragments that have opted to retain their instance across
* configuration changes.
*/
public List<Fragment> retainNonConfig() {
return mHost.mFragmentManager.retainNonConfig();
}
/**
* Moves all Fragments managed by the controller's FragmentManager
* into the create state.
* <p>Call when Fragments should be created.
*
* @see Fragment#onCreate(Bundle)
*/
public void dispatchCreate() {
mHost.mFragmentManager.dispatchCreate();
}
/**
* Moves all Fragments managed by the controller's FragmentManager
* into the activity created state.
* <p>Call when Fragments should be informed their host has been created.
*
* @see Fragment#onActivityCreated(Bundle)
*/
public void dispatchActivityCreated() {
mHost.mFragmentManager.dispatchActivityCreated();
}
/**
* Moves all Fragments managed by the controller's FragmentManager
* into the start state.
* <p>Call when Fragments should be started.
*
* @see Fragment#onStart()
*/
public void dispatchStart() {
mHost.mFragmentManager.dispatchStart();
}
/**
* Moves all Fragments managed by the controller's FragmentManager
* into the resume state.
* <p>Call when Fragments should be resumed.
*
* @see Fragment#onResume()
*/
public void dispatchResume() {
mHost.mFragmentManager.dispatchResume();
}
/**
* Moves all Fragments managed by the controller's FragmentManager
* into the pause state.
* <p>Call when Fragments should be paused.
*
* @see Fragment#onPause()
*/
public void dispatchPause() {
mHost.mFragmentManager.dispatchPause();
}
/**
* Moves all Fragments managed by the controller's FragmentManager
* into the stop state.
* <p>Call when Fragments should be stopped.
*
* @see Fragment#onStop()
*/
public void dispatchStop() {
mHost.mFragmentManager.dispatchStop();
}
/**
* Moves all Fragments managed by the controller's FragmentManager
* into the destroy view state.
* <p>Call when the Fragment's views should be destroyed.
*
* @see Fragment#onDestroyView()
*/
public void dispatchDestroyView() {
mHost.mFragmentManager.dispatchDestroyView();
}
/**
* Moves all Fragments managed by the controller's FragmentManager
* into the destroy state.
* <p>Call when Fragments should be destroyed.
*
* @see Fragment#onDestroy()
*/
public void dispatchDestroy() {
mHost.mFragmentManager.dispatchDestroy();
}
/**
* Lets all Fragments managed by the controller's FragmentManager
* know a configuration change occurred.
* <p>Call when there is a configuration change.
*
* @see Fragment#onConfigurationChanged(Configuration)
*/
public void dispatchConfigurationChanged(Configuration newConfig) {
mHost.mFragmentManager.dispatchConfigurationChanged(newConfig);
}
/**
* Lets all Fragments managed by the controller's FragmentManager
* know the device is in a low memory condition.
* <p>Call when the device is low on memory and Fragment's should trim
* their memory usage.
*
* @see Fragment#onLowMemory()
*/
public void dispatchLowMemory() {
mHost.mFragmentManager.dispatchLowMemory();
}
/**
* Lets all Fragments managed by the controller's FragmentManager
* know they should trim their memory usage.
* <p>Call when the Fragment can release allocated memory [such as if
* the Fragment is in the background].
*
* @see Fragment#onTrimMemory(int)
*/
public void dispatchTrimMemory(int level) {
mHost.mFragmentManager.dispatchTrimMemory(level);
}
/**
* Lets all Fragments managed by the controller's FragmentManager
* know they should create an options menu.
* <p>Call when the Fragment should create an options menu.
*
* @return {@code true} if the options menu contains items to display
* @see Fragment#onCreateOptionsMenu(Menu, MenuInflater)
*/
public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
return mHost.mFragmentManager.dispatchCreateOptionsMenu(menu, inflater);
}
/**
* Lets all Fragments managed by the controller's FragmentManager
* know they should prepare their options menu for display.
* <p>Call immediately before displaying the Fragment's options menu.
*
* @return {@code true} if the options menu contains items to display
* @see Fragment#onPrepareOptionsMenu(Menu)
*/
public boolean dispatchPrepareOptionsMenu(Menu menu) {
return mHost.mFragmentManager.dispatchPrepareOptionsMenu(menu);
}
/**
* Sends an option item selection event to the Fragments managed by the
* controller's FragmentManager. Once the event has been consumed,
* no additional handling will be performed.
* <p>Call immediately after an options menu item has been selected
*
* @return {@code true} if the options menu selection event was consumed
* @see Fragment#onOptionsItemSelected(MenuItem)
*/
public boolean dispatchOptionsItemSelected(MenuItem item) {
return mHost.mFragmentManager.dispatchOptionsItemSelected(item);
}
/**
* Sends a context item selection event to the Fragments managed by the
* controller's FragmentManager. Once the event has been consumed,
* no additional handling will be performed.
* <p>Call immediately after an options menu item has been selected
*
* @return {@code true} if the context menu selection event was consumed
* @see Fragment#onContextItemSelected(MenuItem)
*/
public boolean dispatchContextItemSelected(MenuItem item) {
return mHost.mFragmentManager.dispatchContextItemSelected(item);
}
/**
* Lets all Fragments managed by the controller's FragmentManager
* know their options menu has closed.
* <p>Call immediately after closing the Fragment's options menu.
*
* @see Fragment#onOptionsMenuClosed(Menu)
*/
public void dispatchOptionsMenuClosed(Menu menu) {
mHost.mFragmentManager.dispatchOptionsMenuClosed(menu);
}
/**
* Execute any pending actions for the Fragments managed by the
* controller's FragmentManager.
* <p>Call when queued actions can be performed [eg when the
* Fragment moves into a start or resume state].
* @return {@code true} if queued actions were performed
*/
public boolean execPendingActions() {
return mHost.mFragmentManager.execPendingActions();
}
/**
* Starts the loaders.
*/
public 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
*/
public void doLoaderStop(boolean retain) {
mHost.doLoaderStop(retain);
}
/**
* Destroys the loaders and, if their state is not being retained, removes them.
*/
public void doLoaderDestroy() {
mHost.doLoaderDestroy();
}
/**
* Lets the loaders know the host is ready to receive notifications.
*/
public void reportLoaderStart() {
mHost.reportLoaderStart();
}
/**
* Returns a list of LoaderManagers that have opted to retain their instance across
* configuration changes.
*/
public ArrayMap<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(ArrayMap<String, LoaderManager> loaderManagers) {
mHost.restoreLoaderNonConfig(loaderManagers);
}
/**
* Dumps the current state of the loaders.
*/
public void dumpLoaders(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
mHost.dumpLoaders(prefix, fd, writer, args);
}
}

View File

@ -0,0 +1,315 @@
/*
* 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.app;
import android.annotation.Nullable;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Integration points with the Fragment host.
* <p>
* Fragments may be hosted by any object; such as an {@link Activity}. In order to
* host fragments, implement {@link FragmentHostCallback}, overriding the methods
* applicable to the host.
*/
public abstract class FragmentHostCallback<E> extends FragmentContainer {
private final Activity mActivity;
final Context mContext;
private final Handler mHandler;
final int mWindowAnimations;
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
private ArrayMap<String, LoaderManager> mAllLoaderManagers;
private LoaderManagerImpl mLoaderManager;
private boolean mCheckedForLoaderManager;
private boolean mLoadersStarted;
public FragmentHostCallback(Context context, Handler handler, int windowAnimations) {
this(null /*activity*/, context, handler, windowAnimations);
}
FragmentHostCallback(Activity activity) {
this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);
}
FragmentHostCallback(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 onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
}
/**
* Return {@code true} if the fragment's state needs to be saved.
*/
public boolean onShouldSaveFragmentState(Fragment fragment) {
return true;
}
/**
* Return a {@link LayoutInflater}.
* See {@link Activity#getLayoutInflater()}.
*/
public LayoutInflater onGetLayoutInflater() {
return (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/**
* Return {@code true} if the FragmentManager's LayoutInflaterFactory should be used.
*/
public boolean onUseFragmentManagerInflaterFactory() {
return false;
}
/**
* Return the object that's currently hosting the fragment. If a {@link Fragment}
* is hosted by a {@link Activity}, the object returned here should be the same
* object returned from {@link Fragment#getActivity()}.
*/
@Nullable
public abstract E onGetHost();
/**
* Invalidates the activity's options menu.
* See {@link Activity#invalidateOptionsMenu()}
*/
public void onInvalidateOptionsMenu() {
}
/**
* Starts a new {@link Activity} from the given fragment.
* See {@link Activity#startActivityForResult(Intent, int)}.
*/
public void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
Bundle options) {
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 onHasWindowAnimations() {
return true;
}
/**
* Return the window animations.
*/
public int onGetWindowAnimations() {
return mWindowAnimations;
}
@Nullable
@Override
public View onFindViewById(int id) {
return null;
}
@Override
public boolean onHasView() {
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);
}
mCheckedForLoaderManager = true;
}
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 ArrayMap<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;
}
ArrayMap<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(ArrayMap<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);
}
}
}

View File

@ -19,9 +19,7 @@ package android.app;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
import android.content.Context;
import android.annotation.IdRes;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
@ -48,6 +46,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Interface for interacting with {@link Fragment} objects inside of an
@ -392,15 +391,6 @@ final class FragmentManagerState implements Parcelable {
};
}
/**
* 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.
*/
@ -430,7 +420,8 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
int mCurState = Fragment.INITIALIZING;
Activity mActivity;
FragmentHostCallback<?> mHost;
FragmentController mController;
FragmentContainer mContainer;
Fragment mParent;
@ -455,10 +446,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
Log.e(TAG, ex.getMessage());
LogWriter logw = new LogWriter(Log.ERROR, TAG);
PrintWriter pw = new FastPrintWriter(logw, false, 1024);
if (mActivity != null) {
if (mHost != null) {
Log.e(TAG, "Activity state:");
try {
mActivity.dump(" ", null, pw, new String[] { });
mHost.onDump(" ", null, pw, new String[] { });
} catch (Exception e) {
pw.flush();
Log.e(TAG, "Failed dumping state", e);
@ -490,7 +481,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
public void popBackStack() {
enqueueAction(new Runnable() {
@Override public void run() {
popBackStackState(mActivity.mHandler, null, -1, 0);
popBackStackState(mHost.getHandler(), null, -1, 0);
}
}, false);
}
@ -499,14 +490,14 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
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);
}
@ -515,7 +506,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
public boolean popBackStackImmediate(String name, int flags) {
checkStateLoss();
executePendingTransactions();
return popBackStackState(mActivity.mHandler, name, -1, flags);
return popBackStackState(mHost.getHandler(), name, -1, flags);
}
@Override
@ -525,7 +516,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
enqueueAction(new Runnable() {
@Override public void run() {
popBackStackState(mActivity.mHandler, null, id, flags);
popBackStackState(mHost.getHandler(), null, id, flags);
}
}, false);
}
@ -537,7 +528,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
if (id < 0) {
throw new IllegalArgumentException("Bad id: " + id);
}
return popBackStackState(mActivity.mHandler, null, id, flags);
return popBackStackState(mHost.getHandler(), null, id, flags);
}
@Override
@ -619,7 +610,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
if (mParent != null) {
DebugUtils.buildShortClassTag(mParent, sb);
} else {
DebugUtils.buildShortClassTag(mActivity, sb);
DebugUtils.buildShortClassTag(mHost, sb);
}
sb.append("}}");
return sb.toString();
@ -716,7 +707,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
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);
@ -747,7 +738,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
if (fragment.mNextAnim != 0) {
Animator anim = AnimatorInflater.loadAnimator(mActivity, fragment.mNextAnim);
Animator anim = AnimatorInflater.loadAnimator(mHost.getContext(), fragment.mNextAnim);
if (anim != null) {
return anim;
}
@ -762,14 +753,14 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
return null;
}
if (transitionStyle == 0 && mActivity.getWindow() != null) {
transitionStyle = mActivity.getWindow().getAttributes().windowAnimations;
if (transitionStyle == 0 && mHost.onHasWindowAnimations()) {
transitionStyle = mHost.onGetWindowAnimations();
}
if (transitionStyle == 0) {
return null;
}
TypedArray attrs = mActivity.obtainStyledAttributes(transitionStyle,
TypedArray attrs = mHost.getContext().obtainStyledAttributes(transitionStyle,
com.android.internal.R.styleable.FragmentAnimation);
int anim = attrs.getResourceId(styleIndex, 0);
attrs.recycle();
@ -778,7 +769,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
return null;
}
return AnimatorInflater.loadAnimator(mActivity, anim);
return AnimatorInflater.loadAnimator(mHost.getContext(), anim);
}
public void performPendingDeferredStart(Fragment f) {
@ -848,18 +839,18 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
}
}
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) {
@ -884,7 +875,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
container = (ViewGroup)mContainer.findViewById(f.mContainerId);
container = (ViewGroup)mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
throwException(new IllegalArgumentException(
"No view found for id 0x"
@ -954,7 +945,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
if (f.mView != null) {
// Need to save the current view state if not
// done already.
if (!mActivity.isFinishing() && f.mSavedViewState == null) {
if (!mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
@ -1030,7 +1021,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
if (!f.mRetaining) {
makeInactive(f);
} else {
f.mActivity = null;
f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
f.mChildFragmentManager = null;
@ -1053,7 +1044,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
void moveToState(int newState, int transit, int transitStyle, boolean always) {
if (mActivity == null && newState != Fragment.INITIALIZING) {
if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No activity");
}
@ -1078,8 +1069,8 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
startPendingDeferredFragments();
}
if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
mActivity.invalidateOptionsMenu();
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
@ -1126,7 +1117,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
mAvailIndices = new ArrayList<Integer>();
}
mAvailIndices.add(f.mIndex);
mActivity.invalidateFragment(f.mWho);
mHost.inactivateFragment(f.mWho);
f.initState();
}
@ -1349,7 +1340,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mActivity == null) {
if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
@ -1357,8 +1348,8 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mActivity.mHandler.removeCallbacks(mExecCommit);
mActivity.mHandler.post(mExecCommit);
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
@ -1427,7 +1418,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
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");
}
@ -1447,7 +1438,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
mPendingActions.toArray(mTmpActions);
mPendingActions.clear();
mActivity.mHandler.removeCallbacks(mExecCommit);
mHost.getHandler().removeCallbacks(mExecCommit);
}
mExecutingActions = true;
@ -1737,7 +1728,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
return fms;
}
void restoreAllState(Parcelable state, ArrayList<Fragment> nonConfig) {
void restoreAllState(Parcelable state, List<Fragment> nonConfig) {
// If there is no saved state at all, then there can not be
// any nonConfig fragments either, so that is that.
if (state == null) return;
@ -1758,7 +1749,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
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;
@ -1775,7 +1766,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
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
@ -1851,9 +1842,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
}
}
public void attachActivity(Activity activity, FragmentContainer container, Fragment parent) {
if (mActivity != null) throw new IllegalStateException("Already attached");
mActivity = activity;
public void attachController(FragmentHostCallback<?> host, FragmentContainer container,
Fragment parent) {
if (mHost != null) throw new IllegalStateException("Already attached");
mHost = host;
mContainer = container;
mParent = parent;
}
@ -1898,7 +1890,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
mDestroyed = true;
execPendingActions();
moveToState(Fragment.INITIALIZING, false);
mActivity = null;
mHost = null;
mContainer = null;
mParent = null;
}
@ -2024,8 +2016,8 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
@Override
public void invalidateOptionsMenu() {
if (mActivity != null && mCurState == Fragment.RESUMED) {
mActivity.invalidateOptionsMenu();
if (mHost != null && mCurState == Fragment.RESUMED) {
mHost.onInvalidateOptionsMenu();
} else {
mNeedMenuInvalidate = true;
}
@ -2115,7 +2107,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
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) {
// A fragment already exists and it is not one we restored from
@ -2132,7 +2124,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
// 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);
}
}

View File

@ -214,12 +214,12 @@ class LoaderManagerImpl extends LoaderManager {
final String mWho;
Activity mActivity;
boolean mStarted;
boolean mRetaining;
boolean mRetainingStarted;
boolean mCreatingLoader;
private FragmentHostCallback mHost;
final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,
Loader.OnLoadCanceledListener<Object> {
@ -356,15 +356,15 @@ class LoaderManagerImpl extends LoaderManager {
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;
}
}
}
@ -465,25 +465,25 @@ class LoaderManagerImpl extends LoaderManager {
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;
@ -530,14 +530,14 @@ class LoaderManagerImpl extends LoaderManager {
}
}
LoaderManagerImpl(String who, Activity activity, boolean started) {
LoaderManagerImpl(String who, FragmentHostCallback host, boolean started) {
mWho = who;
mActivity = activity;
mHost = host;
mStarted = started;
}
void updateActivity(Activity activity) {
mActivity = activity;
void updateHostController(FragmentHostCallback host) {
mHost = host;
}
private LoaderInfo createLoader(int id, Bundle args,
@ -730,8 +730,8 @@ class LoaderManagerImpl extends LoaderManager {
mInactiveLoaders.removeAt(idx);
info.destroy();
}
if (mActivity != null && !hasRunningLoaders()) {
mActivity.mFragments.startPendingDeferredFragments();
if (mHost != null && !hasRunningLoaders()) {
mHost.mFragmentManager.startPendingDeferredFragments();
}
}
@ -849,7 +849,7 @@ class LoaderManagerImpl extends LoaderManager {
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();
}