summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt4
-rw-r--r--core/java/android/app/Fragment.java39
-rw-r--r--core/java/android/app/FragmentManager.java38
3 files changed, 60 insertions, 21 deletions
diff --git a/api/current.txt b/api/current.txt
index 4e41c29..cc7f0798 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3235,6 +3235,7 @@ package android.app {
method public final android.app.Fragment getTargetFragment();
method public final int getTargetRequestCode();
method public final java.lang.CharSequence getText(int);
+ method public boolean getUserVisibleHint();
method public android.view.View getView();
method public final int hashCode();
method public static android.app.Fragment instantiate(android.content.Context, java.lang.String);
@@ -3245,7 +3246,6 @@ 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);
@@ -3281,8 +3281,8 @@ 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 setUserVisibleHint(boolean);
method public void startActivity(android.content.Intent);
method public void startActivityForResult(android.content.Intent, int);
method public void unregisterForContextMenu(android.view.View);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 9b01b7f..473a2d1 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -458,6 +458,9 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
// have been started and their loaders are finished.
boolean mDeferStart;
+ // Hint provided by the app that this fragment is currently visible to the user.
+ boolean mUserVisibleHint = true;
+
LoaderManagerImpl mLoaderManager;
boolean mLoadersStarted;
boolean mCheckedForLoaderManager;
@@ -915,31 +918,32 @@ 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.
+ * Set a hint to the system about whether this fragment's UI is currently visible
+ * to the user. This hint defaults to true and is persistent across fragment instance
+ * state save and restore.
*
- * <p>This option is not sticky across fragment starts; after a deferred start
- * completes this option will be set to false.</p>
+ * <p>An app may set this to false to indicate that the fragment's UI is
+ * scrolled out of visibility or is otherwise not directly visible to the user.
+ * This may be used by the system to prioritize operations such as fragment lifecycle updates
+ * or loader ordering behavior.</p>
*
- * @param deferResume true if this fragment can defer its resume until after others
+ * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default),
+ * false if it is not.
*/
- public void setStartDeferred(boolean deferResume) {
- if (mDeferStart && !deferResume) {
+ public void setUserVisibleHint(boolean isVisibleToUser) {
+ if (!mUserVisibleHint && isVisibleToUser && mState < STARTED) {
mFragmentManager.performPendingDeferredStart(this);
}
- mDeferStart = deferResume;
+ mUserVisibleHint = isVisibleToUser;
+ mDeferStart = !isVisibleToUser;
}
/**
- * 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.
+ * @return The current value of the user-visible hint on this fragment.
+ * @see #setUserVisibleHint(boolean)
*/
- public boolean isStartDeferred() {
- return mDeferStart;
+ public boolean getUserVisibleHint() {
+ return mUserVisibleHint;
}
/**
@@ -1477,7 +1481,8 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
writer.print(" mMenuVisible="); writer.print(mMenuVisible);
writer.print(" mHasMenu="); writer.println(mHasMenu);
writer.print(prefix); writer.print("mRetainInstance="); writer.print(mRetainInstance);
- writer.print(" mRetaining="); writer.println(mRetaining);
+ writer.print(" mRetaining="); writer.print(mRetaining);
+ writer.print(" mUserVisibleHint="); writer.println(mUserVisibleHint);
if (mFragmentManager != null) {
writer.print(prefix); writer.print("mFragmentManager=");
writer.println(mFragmentManager);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index c4ba778..a8c9cba 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -382,6 +382,7 @@ final class FragmentManagerImpl extends FragmentManager {
static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
static final String TARGET_STATE_TAG = "android:target_state";
static final String VIEW_STATE_TAG = "android:view_state";
+ static final String USER_VISIBLE_HINT_TAG = "android:user_visible_hint";
ArrayList<Runnable> mPendingActions;
Runnable[] mTmpActions;
@@ -406,6 +407,7 @@ final class FragmentManagerImpl extends FragmentManager {
boolean mStateSaved;
boolean mDestroyed;
String mNoTransactionsBecause;
+ boolean mHavePendingDeferredStart;
// Temporary vars for state save and restore.
Bundle mStateBundle = null;
@@ -711,6 +713,11 @@ final class FragmentManagerImpl extends FragmentManager {
public void performPendingDeferredStart(Fragment f) {
if (f.mDeferStart) {
+ if (mExecutingActions) {
+ // Wait until we're done executing our pending transactions
+ mHavePendingDeferredStart = true;
+ return;
+ }
f.mDeferStart = false;
moveToState(f, mCurState, 0, 0);
}
@@ -757,6 +764,14 @@ final class FragmentManagerImpl extends FragmentManager {
f.mTargetRequestCode = f.mSavedFragmentState.getInt(
FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
}
+ f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
+ FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
+ if (!f.mUserVisibleHint) {
+ f.mDeferStart = true;
+ if (newState > Fragment.STOPPED) {
+ newState = Fragment.STOPPED;
+ }
+ }
}
f.mActivity = mActivity;
f.mFragmentManager = mActivity.mFragments;
@@ -1343,7 +1358,7 @@ final class FragmentManagerImpl extends FragmentManager {
synchronized (this) {
if (mPendingActions == null || mPendingActions.size() == 0) {
- return didSomething;
+ break;
}
numActions = mPendingActions.size();
@@ -1363,8 +1378,23 @@ final class FragmentManagerImpl extends FragmentManager {
mExecutingActions = false;
didSomething = true;
}
+
+ if (mHavePendingDeferredStart) {
+ boolean loadersRunning = false;
+ for (int i=0; i<mActive.size(); i++) {
+ Fragment f = mActive.get(i);
+ if (f != null && f.mLoaderManager != null) {
+ loadersRunning |= f.mLoaderManager.hasRunningLoaders();
+ }
+ }
+ if (!loadersRunning) {
+ mHavePendingDeferredStart = false;
+ startPendingDeferredFragments();
+ }
+ }
+ return didSomething;
}
-
+
void reportBackStackChanged() {
if (mBackStackChangeListeners != null) {
for (int i=0; i<mBackStackChangeListeners.size(); i++) {
@@ -1500,6 +1530,10 @@ final class FragmentManagerImpl extends FragmentManager {
result.putSparseParcelableArray(
FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
}
+ if (!f.mUserVisibleHint) {
+ // Only add this if it's not the default value
+ result.putBoolean(FragmentManagerImpl.USER_VISIBLE_HINT_TAG, f.mUserVisibleHint);
+ }
return result;
}