diff --git a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java index f6682abbb58d..f21fadf0fa30 100644 --- a/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java +++ b/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java @@ -241,6 +241,10 @@ public Intent build(@NonNull Context context) { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { switchLaunchThemeForNormalTheme(); + // Get an existing fragment reference first before onCreate since onCreate would re-attach + // existing fragments. This would cause FlutterFragment to reference the host activity which + // should be aware of its child fragment. + flutterFragment = retrieveExistingFlutterFragmentIfPossible(); super.onCreate(savedInstanceState); @@ -366,21 +370,31 @@ private View createFragmentContainer() { return container; } + /** + * Retrieves the previously created {@link FlutterFragment} if possible. + * + *

If the activity is recreated, an existing {@link FlutterFragment} may already exist. Retain + * a reference to that {@link FlutterFragment} in the {@code #flutterFragment} field and avoid + * re-creating another {@link FlutterFragment}. + */ + @VisibleForTesting + FlutterFragment retrieveExistingFlutterFragmentIfPossible() { + FragmentManager fragmentManager = getSupportFragmentManager(); + return (FlutterFragment) fragmentManager.findFragmentByTag(TAG_FLUTTER_FRAGMENT); + } + /** * Ensure that a {@link FlutterFragment} is attached to this {@code FlutterFragmentActivity}. * *

If no {@link FlutterFragment} exists in this {@code FlutterFragmentActivity}, then a {@link - * FlutterFragment} is created and added. If a {@link FlutterFragment} does exist in this {@code - * FlutterFragmentActivity}, then a reference to that {@link FlutterFragment} is retained in - * {@code #flutterFragment}. + * FlutterFragment} is created and added. */ private void ensureFlutterFragmentCreated() { - FragmentManager fragmentManager = getSupportFragmentManager(); - flutterFragment = (FlutterFragment) fragmentManager.findFragmentByTag(TAG_FLUTTER_FRAGMENT); if (flutterFragment == null) { // No FlutterFragment exists yet. This must be the initial Activity creation. We will create // and add a new FlutterFragment to this Activity. flutterFragment = createFlutterFragment(); + FragmentManager fragmentManager = getSupportFragmentManager(); fragmentManager .beginTransaction() .add(FRAGMENT_CONTAINER_ID, flutterFragment, TAG_FLUTTER_FRAGMENT) diff --git a/shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java b/shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java index 0872c56196ff..1b14a4a6e463 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java @@ -3,6 +3,7 @@ import static io.flutter.embedding.android.FlutterActivityLaunchConfigs.HANDLE_DEEPLINKING_META_DATA_KEY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -170,7 +171,37 @@ public void itAllowsRootLayoutOverride() { assertTrue(foundCustomView); } + @Test + public void itCreatesAValidFlutterFragment() { + FlutterFragmentActivityWithProvidedEngine activity = + Robolectric.buildActivity(FlutterFragmentActivityWithProvidedEngine.class).get(); + + // Creating the FlutterFragmentActivity will create and attach the FlutterFragment, causing + // a FlutterEngine to be created. + activity.onCreate(null); + assertNotNull(activity.getFlutterEngine()); + assertEquals(1, activity.numberOfEnginesCreated); + } + + @Test + public void itRetrievesExistingFlutterFragmentWhenRecreated() { + FlutterFragmentActivityWithProvidedEngine activity = + spy(Robolectric.buildActivity(FlutterFragmentActivityWithProvidedEngine.class).get()); + + FlutterFragment fragment = mock(FlutterFragment.class); + when(activity.retrieveExistingFlutterFragmentIfPossible()).thenReturn(fragment); + + FlutterEngine engine = mock(FlutterEngine.class); + when(fragment.getFlutterEngine()).thenReturn(engine); + + activity.onCreate(null); + assertEquals(engine, activity.getFlutterEngine()); + assertEquals(0, activity.numberOfEnginesCreated); + } + static class FlutterFragmentActivityWithProvidedEngine extends FlutterFragmentActivity { + int numberOfEnginesCreated = 0; + @Override protected FlutterFragment createFlutterFragment() { return FlutterFragment.createDefault(); @@ -184,6 +215,7 @@ public FlutterEngine provideFlutterEngine(@NonNull Context context) { when(flutterJNI.isAttached()).thenReturn(true); when(flutterLoader.automaticallyRegisterPlugins()).thenReturn(true); + numberOfEnginesCreated++; return new FlutterEngine(context, flutterLoader, flutterJNI, new String[] {}, true); } }