diff options
author | Adam Powell <adamp@google.com> | 2011-11-07 10:45:34 -0800 |
---|---|---|
committer | Adam Powell <adamp@google.com> | 2011-11-07 13:47:13 -0800 |
commit | 78fed9b78f8b3b92979b94dda2640cdeaffb2573 (patch) | |
tree | 5f6fad0fc41951675618420422218c03758d5b11 /core/java/android | |
parent | 19c86cacb2f0ba04cc93084ba474662afb17d88f (diff) | |
download | frameworks_base-78fed9b78f8b3b92979b94dda2640cdeaffb2573.zip frameworks_base-78fed9b78f8b3b92979b94dda2640cdeaffb2573.tar.gz frameworks_base-78fed9b78f8b3b92979b94dda2640cdeaffb2573.tar.bz2 |
Change the "start deferred" fragment API to "user visible hint"
Allow a fragment to set a hint of whether or not it is currently user
visible. This will be used implicitly to defer the start of fragments
that are not user visible until the loaders for visible fragments have
run. This hint defaults to true.
Change-Id: Id1349d319886a277ef07301f64f7b9e12c8729bf
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/app/Fragment.java | 39 | ||||
-rw-r--r-- | core/java/android/app/FragmentManager.java | 38 |
2 files changed, 58 insertions, 19 deletions
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; } |