Retain loaders through stopped config changes
Framework edition Previously we would throw away any stopped LoaderManagers when we went to retain instances to pass along as nonConfigurationInstances during config changes or similar activity restarts. This causes loaders to do more work than they need to when a calling activity starts a new activity on top, a config change happens (e.g. screen rotation) and then the top activity is finished, restarting the caller in a new configuration. The loaders would go through onReset unnecessarily, potentially throwing away data to be reloaded again after the config change completes. Instead of throwing away stopped LoaderManagers in this case, restart them and retain them across the config change so they can resume where they left off. Bug 27176186 Change-Id: Ia52c6448d2ad41dcb25d493770d9ffae20a19d2a
This commit is contained in:
@@ -2098,7 +2098,15 @@ public class Activity extends ContextThemeWrapper
|
||||
Object activity = onRetainNonConfigurationInstance();
|
||||
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
|
||||
FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();
|
||||
|
||||
// We're already stopped but we've been asked to retain.
|
||||
// Our fragments are taken care of but we need to mark the loaders for retention.
|
||||
// In order to do this correctly we need to restart the loaders first before
|
||||
// handing them off to the next activity.
|
||||
mFragments.doLoaderStart();
|
||||
mFragments.doLoaderStop(true);
|
||||
ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();
|
||||
|
||||
if (activity == null && children == null && fragments == null && loaders == null
|
||||
&& mVoiceInteractor == null) {
|
||||
return null;
|
||||
|
||||
@@ -308,15 +308,22 @@ public abstract class FragmentHostCallback<E> extends FragmentContainer {
|
||||
ArrayMap<String, LoaderManager> retainLoaderNonConfig() {
|
||||
boolean retainLoaders = false;
|
||||
if (mAllLoaderManagers != null) {
|
||||
// prune out any loader managers that were already stopped and so
|
||||
// have nothing useful to retain.
|
||||
// Restart any loader managers that were already stopped so that they
|
||||
// will be ready to retain
|
||||
final int N = mAllLoaderManagers.size();
|
||||
LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
|
||||
for (int i=N-1; i>=0; i--) {
|
||||
loaders[i] = (LoaderManagerImpl) mAllLoaderManagers.valueAt(i);
|
||||
}
|
||||
final boolean doRetainLoaders = getRetainLoaders();
|
||||
for (int i=0; i<N; i++) {
|
||||
LoaderManagerImpl lm = loaders[i];
|
||||
if (!lm.mRetaining && doRetainLoaders) {
|
||||
if (!lm.mStarted) {
|
||||
lm.doStart();
|
||||
}
|
||||
lm.doRetain();
|
||||
}
|
||||
if (lm.mRetaining) {
|
||||
retainLoaders = true;
|
||||
} else {
|
||||
|
||||
@@ -1114,7 +1114,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
|
||||
if (!f.mRetaining) {
|
||||
f.performDestroy();
|
||||
} else {
|
||||
f.mState = Fragment.CREATED;
|
||||
f.mState = Fragment.INITIALIZING;
|
||||
}
|
||||
|
||||
f.mCalled = false;
|
||||
|
||||
Reference in New Issue
Block a user