Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 578449f

Browse files
authored
Fix crash when both FlutterFragmentActivity and FlutterFragment are destroyed and recreated (#25851)
1 parent 23cd8e5 commit 578449f

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,12 @@ FlutterFragment retrieveExistingFlutterFragmentIfPossible() {
390390
* FlutterFragment} is created and added.
391391
*/
392392
private void ensureFlutterFragmentCreated() {
393+
if (flutterFragment == null) {
394+
// If both activity and fragment have been destroyed, the activity restore may have
395+
// already recreated a new instance of the fragment again via the FragmentActivity.onCreate
396+
// and the FragmentManager.
397+
flutterFragment = retrieveExistingFlutterFragmentIfPossible();
398+
}
393399
if (flutterFragment == null) {
394400
// No FlutterFragment exists yet. This must be the initial Activity creation. We will create
395401
// and add a new FlutterFragment to this Activity.
@@ -602,7 +608,7 @@ public FlutterEngine provideFlutterEngine(@NonNull Context context) {
602608
*/
603609
@Override
604610
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
605-
if (flutterFragment.isFlutterEngineInjected()) {
611+
if (flutterFragment != null && flutterFragment.isFlutterEngineInjected()) {
606612
// If the FlutterEngine was explicitly built and injected into this FlutterActivity, the
607613
// builder should explicitly decide whether to automatically register plugins via the
608614
// FlutterEngine's construction parameter or via the AndroidManifest metadata.

shell/platform/android/test/io/flutter/embedding/android/FlutterFragmentActivityTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,26 @@ public void itRetrievesExistingFlutterFragmentWhenRecreated() {
199199
assertEquals(0, activity.numberOfEnginesCreated);
200200
}
201201

202+
@Test
203+
public void itHandlesNewFragmentRecreationDuringRestoreWhenActivityIsRecreated() {
204+
FlutterFragmentActivityWithProvidedEngine activity =
205+
spy(Robolectric.buildActivity(FlutterFragmentActivityWithProvidedEngine.class).get());
206+
207+
FlutterFragment fragment = mock(FlutterFragment.class);
208+
// Similar to the above case, except here, it's not just the activity that was destroyed and
209+
// could have its fragment restored in the fragment manager. Here, both activity and fragment
210+
// are destroyed. And the fragment manager recreated the fragment on activity recreate.
211+
when(activity.retrieveExistingFlutterFragmentIfPossible()).thenReturn(null, fragment);
212+
213+
FlutterEngine engine = mock(FlutterEngine.class);
214+
when(fragment.getFlutterEngine()).thenReturn(engine);
215+
216+
activity.onCreate(null);
217+
// The framework would have recreated a new fragment but the fragment activity wouldn't have
218+
// created a new one again.
219+
assertEquals(0, activity.numberOfEnginesCreated);
220+
}
221+
202222
static class FlutterFragmentActivityWithProvidedEngine extends FlutterFragmentActivity {
203223
int numberOfEnginesCreated = 0;
204224

0 commit comments

Comments
 (0)