diff --git a/api/current.xml b/api/current.xml
index db2456a339570..ea7804c4ed7fd 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -26078,6 +26078,17 @@
visibility="public"
>
+
+
-
-
+
+
+
+
+
+
+
+ children = onRetainNonConfigurationChildInstances();
ArrayList fragments = mFragments.retainNonConfig();
- if (activity == null && children == null && fragments == null) {
+ boolean retainLoaders = false;
+ if (mAllLoaderManagers != null) {
+ // prune out any loader managers that were already stopped, so
+ // have nothing useful to retain.
+ for (int i=mAllLoaderManagers.size()-1; i>=0; i--) {
+ LoaderManager lm = mAllLoaderManagers.valueAt(i);
+ if (lm.mRetaining) {
+ retainLoaders = true;
+ } else {
+ mAllLoaderManagers.removeAt(i);
+ }
+ }
+ }
+ if (activity == null && children == null && fragments == null && !retainLoaders) {
return null;
}
@@ -1530,6 +1551,7 @@ public class Activity extends ContextThemeWrapper
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
+ nci.loaders = mAllLoaderManagers;
return nci;
}
@@ -4065,6 +4087,11 @@ public class Activity extends ContextThemeWrapper
" did not call through to super.onStart()");
}
mFragments.dispatchStart();
+ if (mAllLoaderManagers != null) {
+ for (int i=mAllLoaderManagers.size()-1; i>=0; i--) {
+ mAllLoaderManagers.valueAt(i).finishRetain();
+ }
+ }
}
final void performRestart() {
@@ -4136,6 +4163,17 @@ public class Activity extends ContextThemeWrapper
}
final void performStop() {
+ if (mStarted) {
+ mStarted = false;
+ if (mLoaderManager != null) {
+ if (!mChangingConfigurations) {
+ mLoaderManager.doStop();
+ } else {
+ mLoaderManager.doRetain();
+ }
+ }
+ }
+
if (!mStopped) {
if (mWindow != null) {
mWindow.closeAllPanels();
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index da3072cf1ca1c..51cce5ebcbd47 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -158,6 +158,9 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
// True if the fragment is in the list of added fragments.
boolean mAdded;
+ // True if the fragment is in the resumed state.
+ boolean mResumed;
+
// Set to true if this fragment was instantiated from a layout file.
boolean mFromLayout;
@@ -320,6 +323,14 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
return mActivity != null && mActivity.mFragments.mAdded.contains(this);
}
+ /**
+ * Return true if the fragment is in the resumed state. This is true
+ * for the duration of {@link #onResume()} and {@link #onPause()} as well.
+ */
+ final public boolean isResumed() {
+ return mResumed;
+ }
+
/**
* Return true if the fragment is currently visible to the user. This means
* it: (1) has been added, (2) has its view attached to the window, and
@@ -575,10 +586,6 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
*/
public void onStop() {
mCalled = true;
- mStarted = false;
- if (mLoaderManager != null) {
- mLoaderManager.doStop();
- }
}
public void onLowMemory() {
@@ -746,4 +753,18 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener
public boolean onContextItemSelected(MenuItem item) {
return false;
}
+
+ void performStop() {
+ onStop();
+ if (mStarted) {
+ mStarted = false;
+ if (mLoaderManager != null) {
+ if (mActivity == null || !mActivity.mChangingConfigurations) {
+ mLoaderManager.doStop();
+ } else {
+ mLoaderManager.doRetain();
+ }
+ }
+ }
+ }
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index b324dfb2cf0aa..cb928a74d3815 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -238,6 +238,7 @@ public class FragmentManager {
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.mCalled = false;
+ f.mResumed = true;
f.onResume();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
@@ -256,12 +257,13 @@ public class FragmentManager {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onPause()");
}
+ f.mResumed = false;
}
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
f.mCalled = false;
- f.onStop();
+ f.performStop();
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onStop()");
diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java
index a0d2aec9523ed..31e3c40acf053 100644
--- a/core/java/android/app/LoaderManager.java
+++ b/core/java/android/app/LoaderManager.java
@@ -26,6 +26,12 @@ import android.util.SparseArray;
* one or more {@link android.content.Loader} instances associated with it.
*/
public class LoaderManager {
+ final SparseArray mLoaders = new SparseArray();
+ final SparseArray mInactiveLoaders = new SparseArray();
+ boolean mStarted;
+ boolean mRetaining;
+ boolean mRetainingStarted;
+
/**
* Callback interface for a client to interact with the manager.
*/
@@ -35,81 +41,208 @@ public class LoaderManager {
}
final class LoaderInfo implements Loader.OnLoadCompleteListener