Merge "Add API for deferring fragment start." into ics-mr1
This commit is contained in:
@@ -3245,6 +3245,7 @@ package android.app {
|
||||
method public final boolean isInLayout();
|
||||
method public final boolean isRemoving();
|
||||
method public final boolean isResumed();
|
||||
method public boolean isStartDeferred();
|
||||
method public final boolean isVisible();
|
||||
method public void onActivityCreated(android.os.Bundle);
|
||||
method public void onActivityResult(int, int, android.content.Intent);
|
||||
@@ -3280,6 +3281,7 @@ package android.app {
|
||||
method public void setInitialSavedState(android.app.Fragment.SavedState);
|
||||
method public void setMenuVisibility(boolean);
|
||||
method public void setRetainInstance(boolean);
|
||||
method public void setStartDeferred(boolean);
|
||||
method public void setTargetFragment(android.app.Fragment, int);
|
||||
method public void startActivity(android.content.Intent);
|
||||
method public void startActivityForResult(android.content.Intent, int);
|
||||
|
||||
@@ -339,6 +339,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
|
||||
private static final HashMap<String, Class<?>> sClassMap =
|
||||
new HashMap<String, Class<?>>();
|
||||
|
||||
static final int INVALID_STATE = -1; // Invalid state used as a null value.
|
||||
static final int INITIALIZING = 0; // Not yet created.
|
||||
static final int CREATED = 1; // Created.
|
||||
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
|
||||
@@ -403,7 +404,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
|
||||
// The fragment manager we are associated with. Set as soon as the
|
||||
// fragment is used in a transaction; cleared after it has been removed
|
||||
// from all transactions.
|
||||
FragmentManager mFragmentManager;
|
||||
FragmentManagerImpl mFragmentManager;
|
||||
|
||||
// Activity this fragment is attached to.
|
||||
Activity mActivity;
|
||||
@@ -453,6 +454,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
|
||||
// The View generated for this fragment.
|
||||
View mView;
|
||||
|
||||
// Whether this fragment should defer starting until after other fragments
|
||||
// have been started and their loaders are finished.
|
||||
boolean mDeferStart;
|
||||
|
||||
LoaderManagerImpl mLoaderManager;
|
||||
boolean mLoadersStarted;
|
||||
boolean mCheckedForLoaderManager;
|
||||
@@ -909,6 +914,34 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this fragment should enter the started state as normal or if
|
||||
* start should be deferred until a system-determined convenient time, such
|
||||
* as after any loaders have completed their work.
|
||||
*
|
||||
* <p>This option is not sticky across fragment starts; after a deferred start
|
||||
* completes this option will be set to false.</p>
|
||||
*
|
||||
* @param deferResume true if this fragment can defer its resume until after others
|
||||
*/
|
||||
public void setStartDeferred(boolean deferResume) {
|
||||
if (mDeferStart && !deferResume) {
|
||||
mFragmentManager.performPendingDeferredStart(this);
|
||||
}
|
||||
mDeferStart = deferResume;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this fragment's move to the started state has been deferred.
|
||||
* If this returns true it will be started once other fragments' loaders
|
||||
* have finished running.
|
||||
*
|
||||
* @return true if this fragment's start has been deferred.
|
||||
*/
|
||||
public boolean isStartDeferred() {
|
||||
return mDeferStart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the LoaderManager for this fragment, creating it if needed.
|
||||
*/
|
||||
|
||||
@@ -709,6 +709,13 @@ final class FragmentManagerImpl extends FragmentManager {
|
||||
return AnimatorInflater.loadAnimator(mActivity, anim);
|
||||
}
|
||||
|
||||
public void performPendingDeferredStart(Fragment f) {
|
||||
if (f.mDeferStart) {
|
||||
f.mDeferStart = false;
|
||||
moveToState(f, mCurState, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void moveToState(Fragment f, int newState, int transit, int transitionStyle) {
|
||||
// Fragments that are not currently added will sit in the onCreate() state.
|
||||
if (!f.mAdded && newState > Fragment.CREATED) {
|
||||
@@ -718,7 +725,10 @@ final class FragmentManagerImpl extends FragmentManager {
|
||||
// While removing a fragment, we can't change it to a higher state.
|
||||
newState = f.mState;
|
||||
}
|
||||
|
||||
// Defer start if requested; don't allow it to move to STARTED or higher.
|
||||
if (f.mDeferStart && newState > Fragment.STOPPED) {
|
||||
newState = Fragment.STOPPED;
|
||||
}
|
||||
if (f.mState < newState) {
|
||||
// For fragments that are created from a layout, when restoring from
|
||||
// state we don't want to allow them to be created until they are
|
||||
@@ -992,13 +1002,21 @@ final class FragmentManagerImpl extends FragmentManager {
|
||||
|
||||
mCurState = newState;
|
||||
if (mActive != null) {
|
||||
boolean loadersRunning = false;
|
||||
for (int i=0; i<mActive.size(); i++) {
|
||||
Fragment f = mActive.get(i);
|
||||
if (f != null) {
|
||||
moveToState(f, newState, transit, transitStyle);
|
||||
if (f.mLoaderManager != null) {
|
||||
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadersRunning) {
|
||||
startPendingDeferredFragments();
|
||||
}
|
||||
|
||||
if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
|
||||
mActivity.invalidateOptionsMenu();
|
||||
mNeedMenuInvalidate = false;
|
||||
@@ -1006,6 +1024,15 @@ final class FragmentManagerImpl extends FragmentManager {
|
||||
}
|
||||
}
|
||||
|
||||
void startPendingDeferredFragments() {
|
||||
for (int i=0; i<mActive.size(); i++) {
|
||||
Fragment f = mActive.get(i);
|
||||
if (f != null) {
|
||||
performPendingDeferredStart(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void makeActive(Fragment f) {
|
||||
if (f.mIndex >= 0) {
|
||||
return;
|
||||
|
||||
@@ -418,6 +418,10 @@ class LoaderManagerImpl extends LoaderManager {
|
||||
info.destroy();
|
||||
mInactiveLoaders.remove(mId);
|
||||
}
|
||||
|
||||
if (!hasRunningLoaders() && mActivity != null) {
|
||||
mActivity.mFragments.startPendingDeferredFragments();
|
||||
}
|
||||
}
|
||||
|
||||
void callOnLoadFinished(Loader<Object> loader, Object data) {
|
||||
@@ -820,4 +824,14 @@ class LoaderManagerImpl extends LoaderManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasRunningLoaders() {
|
||||
boolean loadersRunning = false;
|
||||
final int count = mLoaders.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final LoaderInfo li = mLoaders.valueAt(i);
|
||||
loadersRunning |= li.mStarted && !li.mDeliveredData;
|
||||
}
|
||||
return loadersRunning;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user