diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-06-10 17:03:42 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2011-06-10 18:34:54 -0700 |
commit | afc4b283fdaedec9bf32492a019b43cc33edc9b6 (patch) | |
tree | 6fde7ed8d76aa76bd93eebc427d4ceb0282d71ea | |
parent | 2bb2d48f9ca1726b8de957ec7ea321c767409c12 (diff) | |
download | frameworks_base-afc4b283fdaedec9bf32492a019b43cc33edc9b6.zip frameworks_base-afc4b283fdaedec9bf32492a019b43cc33edc9b6.tar.gz frameworks_base-afc4b283fdaedec9bf32492a019b43cc33edc9b6.tar.bz2 |
Fix some problems with moving in and out of detached state.
Loaders were not being re-initialized correctly when coming back
(this would also impact the back stack). The ListView also wasn't
working correctly, and there were also problems with simply
re-using a Fragment instance after it had been removed.
Change-Id: I534b091ae09c0ef7ffffe9d68049e6840e8926b3
-rw-r--r-- | api/current.xml | 11 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 4 | ||||
-rw-r--r-- | core/java/android/app/Fragment.java | 57 | ||||
-rw-r--r-- | core/java/android/app/FragmentManager.java | 6 | ||||
-rw-r--r-- | core/java/android/app/ListFragment.java | 24 | ||||
-rw-r--r-- | core/java/android/app/LoaderManager.java | 33 |
6 files changed, 118 insertions, 17 deletions
diff --git a/api/current.xml b/api/current.xml index 6581042..a9f3e85 100644 --- a/api/current.xml +++ b/api/current.xml @@ -30614,6 +30614,17 @@ visibility="public" > </method> +<method name="isDetached" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="isHidden" return="boolean" abstract="false" diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index b739e10..e0a2ce8 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -4413,7 +4413,9 @@ public class Activity extends ContextThemeWrapper mFragments.dispatchStart(); if (mAllLoaderManagers != null) { for (int i=mAllLoaderManagers.size()-1; i>=0; i--) { - mAllLoaderManagers.valueAt(i).finishRetain(); + LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i); + lm.finishRetain(); + lm.doReportStart(); } } } diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 14ffd3b..f2be9ad 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -587,11 +587,6 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener mWho = "android:fragment:" + mIndex; } - final void clearIndex() { - mIndex = -1; - mWho = null; - } - final boolean isInBackStack() { return mBackStackNesting > 0; } @@ -783,6 +778,15 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener } /** + * Return true if the fragment has been explicitly detached from the UI. + * That is, {@link FragmentTransaction#detach(Fragment) + * FragmentTransaction.detach(Fragment)} has been used on it. + */ + final public boolean isDetached() { + return mDetached; + } + + /** * Return true if this fragment is currently being removed from its * activity. This is <em>not</em> whether its activity is finishing, but * rather whether it is in the process of being removed from its activity. @@ -1203,6 +1207,35 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener } /** + * Called by the fragment manager once this fragment has been removed, + * so that we don't have any left-over state if the application decides + * to re-use the instance. This only clears state that the framework + * internally manages, not things the application sets. + */ + void initState() { + mIndex = -1; + mWho = null; + mAdded = false; + mRemoving = false; + mResumed = false; + mFromLayout = false; + mInLayout = false; + mRestored = false; + mBackStackNesting = 0; + mFragmentManager = null; + mActivity = mImmediateActivity = null; + mFragmentId = 0; + mContainerId = 0; + mTag = null; + mHidden = false; + mDetached = false; + mRetaining = false; + mLoaderManager = null; + mLoadersStarted = false; + mCheckedForLoaderManager = false; + } + + /** * Called when the fragment is no longer attached to its activity. This * is called after {@link #onDestroy()}. */ @@ -1429,6 +1462,13 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener } } + void performStart() { + onStart(); + if (mLoaderManager != null) { + mLoaderManager.doReportStart(); + } + } + void performStop() { onStop(); @@ -1447,4 +1487,11 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener } } } + + void performDestroyView() { + onDestroyView(); + if (mLoaderManager != null) { + mLoaderManager.doReportNextStart(); + } + } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 3b2e108..f05e2b3 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -803,7 +803,7 @@ final class FragmentManagerImpl extends FragmentManager { if (newState > Fragment.STOPPED) { if (DEBUG) Log.v(TAG, "moveto STARTED: " + f); f.mCalled = false; - f.onStart(); + f.performStart(); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onStart()"); @@ -856,7 +856,7 @@ final class FragmentManagerImpl extends FragmentManager { } } f.mCalled = false; - f.onDestroyView(); + f.performDestroyView(); if (!f.mCalled) { throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onDestroyView()"); @@ -1006,7 +1006,7 @@ final class FragmentManagerImpl extends FragmentManager { } mAvailIndices.add(f.mIndex); mActivity.invalidateFragmentIndex(f.mIndex); - f.clearIndex(); + f.initState(); } public void addFragment(Fragment fragment, boolean moveToStateNow) { diff --git a/core/java/android/app/ListFragment.java b/core/java/android/app/ListFragment.java index a5ee26c..dc8420e 100644 --- a/core/java/android/app/ListFragment.java +++ b/core/java/android/app/ListFragment.java @@ -167,7 +167,7 @@ public class ListFragment extends Fragment { TextView mStandardEmptyView; View mProgressContainer; View mListContainer; - boolean mSetEmptyText; + CharSequence mEmptyText; boolean mListShown; public ListFragment() { @@ -210,6 +210,9 @@ public class ListFragment extends Fragment { public void onDestroyView() { mHandler.removeCallbacks(mRequestFocus); mList = null; + mListShown = false; + mEmptyView = mProgressContainer = mListContainer = null; + mStandardEmptyView = null; super.onDestroyView(); } @@ -289,10 +292,10 @@ public class ListFragment extends Fragment { throw new IllegalStateException("Can't be used with a custom content view"); } mStandardEmptyView.setText(text); - if (!mSetEmptyText) { + if (mEmptyText == null) { mList.setEmptyView(mStandardEmptyView); - mSetEmptyText = true; } + mEmptyText = text; } /** @@ -346,6 +349,9 @@ public class ListFragment extends Fragment { getActivity(), android.R.anim.fade_out)); mListContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_in)); + } else { + mProgressContainer.clearAnimation(); + mListContainer.clearAnimation(); } mProgressContainer.setVisibility(View.GONE); mListContainer.setVisibility(View.VISIBLE); @@ -355,6 +361,9 @@ public class ListFragment extends Fragment { getActivity(), android.R.anim.fade_in)); mListContainer.startAnimation(AnimationUtils.loadAnimation( getActivity(), android.R.anim.fade_out)); + } else { + mProgressContainer.clearAnimation(); + mListContainer.clearAnimation(); } mProgressContainer.setVisibility(View.VISIBLE); mListContainer.setVisibility(View.GONE); @@ -383,6 +392,8 @@ public class ListFragment extends Fragment { com.android.internal.R.id.internalEmpty); if (mStandardEmptyView == null) { mEmptyView = root.findViewById(android.R.id.empty); + } else { + mStandardEmptyView.setVisibility(View.GONE); } mProgressContainer = root.findViewById(com.android.internal.R.id.progressContainer); mListContainer = root.findViewById(com.android.internal.R.id.listContainer); @@ -400,12 +411,17 @@ public class ListFragment extends Fragment { } if (mEmptyView != null) { mList.setEmptyView(mEmptyView); + } else if (mEmptyText != null) { + mStandardEmptyView.setText(mEmptyText); + mList.setEmptyView(mStandardEmptyView); } } mListShown = true; mList.setOnItemClickListener(mOnClickListener); if (mAdapter != null) { - setListAdapter(mAdapter); + ListAdapter adapter = mAdapter; + mAdapter = null; + setListAdapter(adapter); } else { // We are starting without an adapter, so assume we won't // have our data right away and start with the progress indicator. diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java index 164141c..46a008d 100644 --- a/core/java/android/app/LoaderManager.java +++ b/core/java/android/app/LoaderManager.java @@ -223,6 +223,7 @@ class LoaderManagerImpl extends LoaderManager { boolean mStarted; boolean mRetaining; boolean mRetainingStarted; + boolean mReportNextStart; boolean mDestroyed; boolean mListenerRegistered; @@ -291,7 +292,7 @@ class LoaderManagerImpl extends LoaderManager { } } - if (mStarted && mHaveData) { + if (mStarted && mHaveData && !mReportNextStart) { // This loader has retained its data, either completely across // a configuration change or just whatever the last data set // was after being restarted from a stop, and now at the point of @@ -302,6 +303,17 @@ class LoaderManagerImpl extends LoaderManager { } } + void reportStart() { + if (mStarted) { + if (mReportNextStart) { + mReportNextStart = false; + if (mHaveData) { + callOnLoadFinished(mLoader, mData); + } + } + } + } + void stop() { if (DEBUG) Log.v(TAG, " Stopping: " + this); mStarted = false; @@ -449,10 +461,11 @@ class LoaderManagerImpl extends LoaderManager { writer.print(prefix); writer.print("mData="); writer.println(mData); } writer.print(prefix); writer.print("mStarted="); writer.print(mStarted); - writer.print(" mRetaining="); writer.print(mRetaining); + writer.print(" mReportNextStart="); writer.print(mReportNextStart); writer.print(" mDestroyed="); writer.println(mDestroyed); - writer.print(prefix); writer.print("mListenerRegistered="); - writer.println(mListenerRegistered); + writer.print(prefix); writer.print("mRetaining="); writer.print(mRetaining); + writer.print(" mRetainingStarted="); writer.print(mRetainingStarted); + writer.print(" mListenerRegistered="); writer.println(mListenerRegistered); if (mPendingLoader != null) { writer.print(prefix); writer.println("Pending Loader "); writer.print(mPendingLoader); writer.println(":"); @@ -740,6 +753,18 @@ class LoaderManagerImpl extends LoaderManager { } } + void doReportNextStart() { + for (int i = mLoaders.size()-1; i >= 0; i--) { + mLoaders.valueAt(i).mReportNextStart = true; + } + } + + void doReportStart() { + for (int i = mLoaders.size()-1; i >= 0; i--) { + mLoaders.valueAt(i).reportStart(); + } + } + void doDestroy() { if (!mRetaining) { if (DEBUG) Log.v(TAG, "Destroying Active in " + this); |