Merge "Fix some problems with moving in and out of detached state." into honeycomb-mr2

This commit is contained in:
Dianne Hackborn
2011-06-10 18:37:22 -07:00
committed by Android (Google) Code Review
6 changed files with 118 additions and 17 deletions

View File

@@ -30614,6 +30614,17 @@
visibility="public" visibility="public"
> >
</method> </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" <method name="isHidden"
return="boolean" return="boolean"
abstract="false" abstract="false"

View File

@@ -4413,7 +4413,9 @@ public class Activity extends ContextThemeWrapper
mFragments.dispatchStart(); mFragments.dispatchStart();
if (mAllLoaderManagers != null) { if (mAllLoaderManagers != null) {
for (int i=mAllLoaderManagers.size()-1; i>=0; i--) { for (int i=mAllLoaderManagers.size()-1; i>=0; i--) {
mAllLoaderManagers.valueAt(i).finishRetain(); LoaderManagerImpl lm = mAllLoaderManagers.valueAt(i);
lm.finishRetain();
lm.doReportStart();
} }
} }
} }

View File

@@ -587,11 +587,6 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
mWho = "android:fragment:" + mIndex; mWho = "android:fragment:" + mIndex;
} }
final void clearIndex() {
mIndex = -1;
mWho = null;
}
final boolean isInBackStack() { final boolean isInBackStack() {
return mBackStackNesting > 0; return mBackStackNesting > 0;
} }
@@ -782,6 +777,15 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
return mActivity != null && mAdded; return mActivity != null && mAdded;
} }
/**
* 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 * Return true if this fragment is currently being removed from its
* activity. This is <em>not</em> whether its activity is finishing, but * activity. This is <em>not</em> whether its activity is finishing, but
@@ -1202,6 +1206,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 * Called when the fragment is no longer attached to its activity. This
* is called after {@link #onDestroy()}. * 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() { void performStop() {
onStop(); onStop();
@@ -1447,4 +1487,11 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
} }
} }
} }
void performDestroyView() {
onDestroyView();
if (mLoaderManager != null) {
mLoaderManager.doReportNextStart();
}
}
} }

View File

@@ -803,7 +803,7 @@ final class FragmentManagerImpl extends FragmentManager {
if (newState > Fragment.STOPPED) { if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f); if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.mCalled = false; f.mCalled = false;
f.onStart(); f.performStart();
if (!f.mCalled) { if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onStart()"); + " did not call through to super.onStart()");
@@ -856,7 +856,7 @@ final class FragmentManagerImpl extends FragmentManager {
} }
} }
f.mCalled = false; f.mCalled = false;
f.onDestroyView(); f.performDestroyView();
if (!f.mCalled) { if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onDestroyView()"); + " did not call through to super.onDestroyView()");
@@ -1006,7 +1006,7 @@ final class FragmentManagerImpl extends FragmentManager {
} }
mAvailIndices.add(f.mIndex); mAvailIndices.add(f.mIndex);
mActivity.invalidateFragmentIndex(f.mIndex); mActivity.invalidateFragmentIndex(f.mIndex);
f.clearIndex(); f.initState();
} }
public void addFragment(Fragment fragment, boolean moveToStateNow) { public void addFragment(Fragment fragment, boolean moveToStateNow) {

View File

@@ -167,7 +167,7 @@ public class ListFragment extends Fragment {
TextView mStandardEmptyView; TextView mStandardEmptyView;
View mProgressContainer; View mProgressContainer;
View mListContainer; View mListContainer;
boolean mSetEmptyText; CharSequence mEmptyText;
boolean mListShown; boolean mListShown;
public ListFragment() { public ListFragment() {
@@ -210,6 +210,9 @@ public class ListFragment extends Fragment {
public void onDestroyView() { public void onDestroyView() {
mHandler.removeCallbacks(mRequestFocus); mHandler.removeCallbacks(mRequestFocus);
mList = null; mList = null;
mListShown = false;
mEmptyView = mProgressContainer = mListContainer = null;
mStandardEmptyView = null;
super.onDestroyView(); super.onDestroyView();
} }
@@ -289,10 +292,10 @@ public class ListFragment extends Fragment {
throw new IllegalStateException("Can't be used with a custom content view"); throw new IllegalStateException("Can't be used with a custom content view");
} }
mStandardEmptyView.setText(text); mStandardEmptyView.setText(text);
if (!mSetEmptyText) { if (mEmptyText == null) {
mList.setEmptyView(mStandardEmptyView); mList.setEmptyView(mStandardEmptyView);
mSetEmptyText = true;
} }
mEmptyText = text;
} }
/** /**
@@ -346,6 +349,9 @@ public class ListFragment extends Fragment {
getActivity(), android.R.anim.fade_out)); getActivity(), android.R.anim.fade_out));
mListContainer.startAnimation(AnimationUtils.loadAnimation( mListContainer.startAnimation(AnimationUtils.loadAnimation(
getActivity(), android.R.anim.fade_in)); getActivity(), android.R.anim.fade_in));
} else {
mProgressContainer.clearAnimation();
mListContainer.clearAnimation();
} }
mProgressContainer.setVisibility(View.GONE); mProgressContainer.setVisibility(View.GONE);
mListContainer.setVisibility(View.VISIBLE); mListContainer.setVisibility(View.VISIBLE);
@@ -355,6 +361,9 @@ public class ListFragment extends Fragment {
getActivity(), android.R.anim.fade_in)); getActivity(), android.R.anim.fade_in));
mListContainer.startAnimation(AnimationUtils.loadAnimation( mListContainer.startAnimation(AnimationUtils.loadAnimation(
getActivity(), android.R.anim.fade_out)); getActivity(), android.R.anim.fade_out));
} else {
mProgressContainer.clearAnimation();
mListContainer.clearAnimation();
} }
mProgressContainer.setVisibility(View.VISIBLE); mProgressContainer.setVisibility(View.VISIBLE);
mListContainer.setVisibility(View.GONE); mListContainer.setVisibility(View.GONE);
@@ -383,6 +392,8 @@ public class ListFragment extends Fragment {
com.android.internal.R.id.internalEmpty); com.android.internal.R.id.internalEmpty);
if (mStandardEmptyView == null) { if (mStandardEmptyView == null) {
mEmptyView = root.findViewById(android.R.id.empty); mEmptyView = root.findViewById(android.R.id.empty);
} else {
mStandardEmptyView.setVisibility(View.GONE);
} }
mProgressContainer = root.findViewById(com.android.internal.R.id.progressContainer); mProgressContainer = root.findViewById(com.android.internal.R.id.progressContainer);
mListContainer = root.findViewById(com.android.internal.R.id.listContainer); mListContainer = root.findViewById(com.android.internal.R.id.listContainer);
@@ -400,12 +411,17 @@ public class ListFragment extends Fragment {
} }
if (mEmptyView != null) { if (mEmptyView != null) {
mList.setEmptyView(mEmptyView); mList.setEmptyView(mEmptyView);
} else if (mEmptyText != null) {
mStandardEmptyView.setText(mEmptyText);
mList.setEmptyView(mStandardEmptyView);
} }
} }
mListShown = true; mListShown = true;
mList.setOnItemClickListener(mOnClickListener); mList.setOnItemClickListener(mOnClickListener);
if (mAdapter != null) { if (mAdapter != null) {
setListAdapter(mAdapter); ListAdapter adapter = mAdapter;
mAdapter = null;
setListAdapter(adapter);
} else { } else {
// We are starting without an adapter, so assume we won't // We are starting without an adapter, so assume we won't
// have our data right away and start with the progress indicator. // have our data right away and start with the progress indicator.

View File

@@ -223,6 +223,7 @@ class LoaderManagerImpl extends LoaderManager {
boolean mStarted; boolean mStarted;
boolean mRetaining; boolean mRetaining;
boolean mRetainingStarted; boolean mRetainingStarted;
boolean mReportNextStart;
boolean mDestroyed; boolean mDestroyed;
boolean mListenerRegistered; 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 // This loader has retained its data, either completely across
// a configuration change or just whatever the last data set // a configuration change or just whatever the last data set
// was after being restarted from a stop, and now at the point of // 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() { void stop() {
if (DEBUG) Log.v(TAG, " Stopping: " + this); if (DEBUG) Log.v(TAG, " Stopping: " + this);
mStarted = false; mStarted = false;
@@ -449,10 +461,11 @@ class LoaderManagerImpl extends LoaderManager {
writer.print(prefix); writer.print("mData="); writer.println(mData); writer.print(prefix); writer.print("mData="); writer.println(mData);
} }
writer.print(prefix); writer.print("mStarted="); writer.print(mStarted); 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(" mDestroyed="); writer.println(mDestroyed);
writer.print(prefix); writer.print("mListenerRegistered="); writer.print(prefix); writer.print("mRetaining="); writer.print(mRetaining);
writer.println(mListenerRegistered); writer.print(" mRetainingStarted="); writer.print(mRetainingStarted);
writer.print(" mListenerRegistered="); writer.println(mListenerRegistered);
if (mPendingLoader != null) { if (mPendingLoader != null) {
writer.print(prefix); writer.println("Pending Loader "); writer.print(prefix); writer.println("Pending Loader ");
writer.print(mPendingLoader); writer.println(":"); 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() { void doDestroy() {
if (!mRetaining) { if (!mRetaining) {
if (DEBUG) Log.v(TAG, "Destroying Active in " + this); if (DEBUG) Log.v(TAG, "Destroying Active in " + this);