Skip to content

Commit 65793dc

Browse files
adampAndroid (Google) Code Review
authored andcommitted
Merge "Add API for deferring fragment start." into ics-mr1
2 parents 43eed00 + 635c60a commit 65793dc

File tree

4 files changed

+78
-2
lines changed

4 files changed

+78
-2
lines changed

api/current.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3245,6 +3245,7 @@ package android.app {
32453245
method public final boolean isInLayout();
32463246
method public final boolean isRemoving();
32473247
method public final boolean isResumed();
3248+
method public boolean isStartDeferred();
32483249
method public final boolean isVisible();
32493250
method public void onActivityCreated(android.os.Bundle);
32503251
method public void onActivityResult(int, int, android.content.Intent);
@@ -3280,6 +3281,7 @@ package android.app {
32803281
method public void setInitialSavedState(android.app.Fragment.SavedState);
32813282
method public void setMenuVisibility(boolean);
32823283
method public void setRetainInstance(boolean);
3284+
method public void setStartDeferred(boolean);
32833285
method public void setTargetFragment(android.app.Fragment, int);
32843286
method public void startActivity(android.content.Intent);
32853287
method public void startActivityForResult(android.content.Intent, int);

core/java/android/app/Fragment.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
339339
private static final HashMap<String, Class<?>> sClassMap =
340340
new HashMap<String, Class<?>>();
341341

342+
static final int INVALID_STATE = -1; // Invalid state used as a null value.
342343
static final int INITIALIZING = 0; // Not yet created.
343344
static final int CREATED = 1; // Created.
344345
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
@@ -403,7 +404,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
403404
// The fragment manager we are associated with. Set as soon as the
404405
// fragment is used in a transaction; cleared after it has been removed
405406
// from all transactions.
406-
FragmentManager mFragmentManager;
407+
FragmentManagerImpl mFragmentManager;
407408

408409
// Activity this fragment is attached to.
409410
Activity mActivity;
@@ -453,6 +454,10 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
453454
// The View generated for this fragment.
454455
View mView;
455456

457+
// Whether this fragment should defer starting until after other fragments
458+
// have been started and their loaders are finished.
459+
boolean mDeferStart;
460+
456461
LoaderManagerImpl mLoaderManager;
457462
boolean mLoadersStarted;
458463
boolean mCheckedForLoaderManager;
@@ -909,6 +914,34 @@ public void setMenuVisibility(boolean menuVisible) {
909914
}
910915
}
911916

917+
/**
918+
* Set whether this fragment should enter the started state as normal or if
919+
* start should be deferred until a system-determined convenient time, such
920+
* as after any loaders have completed their work.
921+
*
922+
* <p>This option is not sticky across fragment starts; after a deferred start
923+
* completes this option will be set to false.</p>
924+
*
925+
* @param deferResume true if this fragment can defer its resume until after others
926+
*/
927+
public void setStartDeferred(boolean deferResume) {
928+
if (mDeferStart && !deferResume) {
929+
mFragmentManager.performPendingDeferredStart(this);
930+
}
931+
mDeferStart = deferResume;
932+
}
933+
934+
/**
935+
* Returns true if this fragment's move to the started state has been deferred.
936+
* If this returns true it will be started once other fragments' loaders
937+
* have finished running.
938+
*
939+
* @return true if this fragment's start has been deferred.
940+
*/
941+
public boolean isStartDeferred() {
942+
return mDeferStart;
943+
}
944+
912945
/**
913946
* Return the LoaderManager for this fragment, creating it if needed.
914947
*/

core/java/android/app/FragmentManager.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,13 @@ Animator loadAnimator(Fragment fragment, int transit, boolean enter,
709709
return AnimatorInflater.loadAnimator(mActivity, anim);
710710
}
711711

712+
public void performPendingDeferredStart(Fragment f) {
713+
if (f.mDeferStart) {
714+
f.mDeferStart = false;
715+
moveToState(f, mCurState, 0, 0);
716+
}
717+
}
718+
712719
void moveToState(Fragment f, int newState, int transit, int transitionStyle) {
713720
// Fragments that are not currently added will sit in the onCreate() state.
714721
if (!f.mAdded && newState > Fragment.CREATED) {
@@ -718,7 +725,10 @@ void moveToState(Fragment f, int newState, int transit, int transitionStyle) {
718725
// While removing a fragment, we can't change it to a higher state.
719726
newState = f.mState;
720727
}
721-
728+
// Defer start if requested; don't allow it to move to STARTED or higher.
729+
if (f.mDeferStart && newState > Fragment.STOPPED) {
730+
newState = Fragment.STOPPED;
731+
}
722732
if (f.mState < newState) {
723733
// For fragments that are created from a layout, when restoring from
724734
// state we don't want to allow them to be created until they are
@@ -992,20 +1002,37 @@ void moveToState(int newState, int transit, int transitStyle, boolean always) {
9921002

9931003
mCurState = newState;
9941004
if (mActive != null) {
1005+
boolean loadersRunning = false;
9951006
for (int i=0; i<mActive.size(); i++) {
9961007
Fragment f = mActive.get(i);
9971008
if (f != null) {
9981009
moveToState(f, newState, transit, transitStyle);
1010+
if (f.mLoaderManager != null) {
1011+
loadersRunning |= f.mLoaderManager.hasRunningLoaders();
1012+
}
9991013
}
10001014
}
10011015

1016+
if (!loadersRunning) {
1017+
startPendingDeferredFragments();
1018+
}
1019+
10021020
if (mNeedMenuInvalidate && mActivity != null && mCurState == Fragment.RESUMED) {
10031021
mActivity.invalidateOptionsMenu();
10041022
mNeedMenuInvalidate = false;
10051023
}
10061024
}
10071025
}
10081026

1027+
void startPendingDeferredFragments() {
1028+
for (int i=0; i<mActive.size(); i++) {
1029+
Fragment f = mActive.get(i);
1030+
if (f != null) {
1031+
performPendingDeferredStart(f);
1032+
}
1033+
}
1034+
}
1035+
10091036
void makeActive(Fragment f) {
10101037
if (f.mIndex >= 0) {
10111038
return;

core/java/android/app/LoaderManager.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,10 @@ void destroy() {
418418
info.destroy();
419419
mInactiveLoaders.remove(mId);
420420
}
421+
422+
if (!hasRunningLoaders() && mActivity != null) {
423+
mActivity.mFragments.startPendingDeferredFragments();
424+
}
421425
}
422426

423427
void callOnLoadFinished(Loader<Object> loader, Object data) {
@@ -820,4 +824,14 @@ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[]
820824
}
821825
}
822826
}
827+
828+
public boolean hasRunningLoaders() {
829+
boolean loadersRunning = false;
830+
final int count = mLoaders.size();
831+
for (int i = 0; i < count; i++) {
832+
final LoaderInfo li = mLoaders.valueAt(i);
833+
loadersRunning |= li.mStarted && !li.mDeliveredData;
834+
}
835+
return loadersRunning;
836+
}
823837
}

0 commit comments

Comments
 (0)