From 592df7d8c61c350033ee35062b12c7d66b9a7c8c Mon Sep 17 00:00:00 2001 From: Adam Powell Date: Thu, 14 Jan 2016 12:58:23 -0800 Subject: [PATCH] Init child fragments consistently with activity fragments Fragments contained within an activity are restored from instance state in FragmentActivity.onCreate, but fragments contained within another fragment were previously restored from instance state in performCreate after onCreate returned. This meant that developers couldn't consistently rely on being able to control when this happens with a call to super.onCreate, and calls to findFragmentByTag to reconnect with a restored child fragment would fail in ways that succeed when the fragment is directly added to an activity. Change child fragment instance state restore to happen during Fragment.onCreate instead of in performCreate to be consistent with activity behavior. Preserve the old behavior for apps targeting an SDK version < N. Change-Id: I9c88d5554da9a32219d64c70ca638f75ecb233ed --- core/java/android/app/Fragment.java | 38 +++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index e163b1c2ad230..20eaf0b8dca46 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; +import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -1416,11 +1417,30 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * at this point. If you want to do work once the activity itself is * created, see {@link #onActivityCreated(Bundle)}. * + *

If your app's targetSdkVersion is 23 or lower, child fragments + * being restored from the savedInstanceState are restored after onCreate + * returns. When targeting N or above and running on an N or newer platform version + * they are restored by Fragment.onCreate.

+ * * @param savedInstanceState If the fragment is being re-created from * a previous saved state, this is the state. */ public void onCreate(@Nullable Bundle savedInstanceState) { mCalled = true; + final Context context = getContext(); + final int version = context != null ? context.getApplicationInfo().targetSdkVersion : 0; + if (version >= Build.VERSION_CODES.N) { + if (savedInstanceState != null) { + Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG); + if (p != null) { + if (mChildFragmentManager == null) { + instantiateChildFragmentManager(); + } + mChildFragmentManager.restoreAllState(p, null); + mChildFragmentManager.dispatchCreate(); + } + } + } } /** @@ -2210,14 +2230,18 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene throw new SuperNotCalledException("Fragment " + this + " did not call through to super.onCreate()"); } - if (savedInstanceState != null) { - Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG); - if (p != null) { - if (mChildFragmentManager == null) { - instantiateChildFragmentManager(); + final Context context = getContext(); + final int version = context != null ? context.getApplicationInfo().targetSdkVersion : 0; + if (version < Build.VERSION_CODES.N) { + if (savedInstanceState != null) { + Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG); + if (p != null) { + if (mChildFragmentManager == null) { + instantiateChildFragmentManager(); + } + mChildFragmentManager.restoreAllState(p, null); + mChildFragmentManager.dispatchCreate(); } - mChildFragmentManager.restoreAllState(p, null); - mChildFragmentManager.dispatchCreate(); } } }