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

Commit 30aa146

Browse files
committed
Started using FlutterEngineGroups by default on Android and making
them accessible to plugins.
1 parent 981fe92 commit 30aa146

11 files changed

+118
-16
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@
147147
*
148148
* <pre>{@code
149149
* // Create and pre-warm a FlutterEngine.
150-
* FlutterEngine flutterEngine = new FlutterEngine(context);
150+
* FlutterEngineGroup group = new FlutterEngineGroup(context);
151+
* FlutterEngine flutterEngine = group.createAndRunDefaultEngine(context);
151152
* flutterEngine.getDartExecutor().executeDartEntrypoint(DartEntrypoint.createDefault());
152153
*
153154
* // Cache the pre-warmed FlutterEngine in the FlutterEngineCache.

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

+18-5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.flutter.Log;
2525
import io.flutter.embedding.engine.FlutterEngine;
2626
import io.flutter.embedding.engine.FlutterEngineCache;
27+
import io.flutter.embedding.engine.FlutterEngineGroup;
2728
import io.flutter.embedding.engine.FlutterShellArgs;
2829
import io.flutter.embedding.engine.dart.DartExecutor;
2930
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
@@ -88,6 +89,7 @@ public interface DelegateFactory {
8889
private boolean isFirstFrameRendered;
8990
private boolean isAttached;
9091
private Integer previousVisibility;
92+
@Nullable private FlutterEngineGroup engineGroup;
9193

9294
@NonNull
9395
private final FlutterUiDisplayListener flutterUiDisplayListener =
@@ -107,8 +109,15 @@ public void onFlutterUiNoLongerDisplayed() {
107109
};
108110

109111
FlutterActivityAndFragmentDelegate(@NonNull Host host) {
112+
this(host, null);
113+
}
114+
115+
FlutterActivityAndFragmentDelegate(@NonNull Host host, @Nullable FlutterEngineGroup engineGroup) {
110116
this.host = host;
111117
this.isFirstFrameRendered = false;
118+
if (engineGroup != null) {
119+
this.engineGroup = engineGroup;
120+
}
112121
}
113122

114123
/**
@@ -264,12 +273,16 @@ void onAttach(@NonNull Context context) {
264273
TAG,
265274
"No preferred FlutterEngine was provided. Creating a new FlutterEngine for"
266275
+ " this FlutterFragment.");
276+
277+
FlutterEngineGroup group =
278+
engineGroup == null
279+
? new FlutterEngineGroup(host.getContext(), host.getFlutterShellArgs().toArray())
280+
: engineGroup;
267281
flutterEngine =
268-
new FlutterEngine(
269-
host.getContext(),
270-
host.getFlutterShellArgs().toArray(),
271-
/*automaticallyRegisterPlugins=*/ false,
272-
/*willProvideRestorationData=*/ host.shouldRestoreAndSaveState());
282+
group.createAndRunEngine(
283+
new FlutterEngineGroup.Options(host.getContext())
284+
.setAutomaticallyRegisterPlugins(false)
285+
.setWaitForRestorationData(host.shouldRestoreAndSaveState()));
273286
isFlutterEngineFromHost = false;
274287
}
275288

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@
7979
*
8080
* <pre>{@code
8181
* // Create and pre-warm a FlutterEngine.
82-
* FlutterEngine flutterEngine = new FlutterEngine(context);
82+
* FlutterEngineGroup group = new FlutterEngineGroup(context);
83+
* FlutterEngine flutterEngine = group.createAndRunDefaultEngine(context);
8384
* flutterEngine
8485
* .getDartExecutor()
8586
* .executeDartEntrypoint(DartEntrypoint.createDefault());

shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import android.content.res.AssetManager;
1010
import androidx.annotation.NonNull;
1111
import androidx.annotation.Nullable;
12+
import androidx.annotation.VisibleForTesting;
1213
import io.flutter.FlutterInjector;
1314
import io.flutter.Log;
1415
import io.flutter.embedding.engine.dart.DartExecutor;
@@ -279,6 +280,27 @@ public FlutterEngine(
279280
@Nullable String[] dartVmArgs,
280281
boolean automaticallyRegisterPlugins,
281282
boolean waitForRestorationData) {
283+
this(
284+
context,
285+
flutterLoader,
286+
flutterJNI,
287+
platformViewsController,
288+
dartVmArgs,
289+
automaticallyRegisterPlugins,
290+
waitForRestorationData,
291+
null);
292+
}
293+
294+
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
295+
public FlutterEngine(
296+
@NonNull Context context,
297+
@Nullable FlutterLoader flutterLoader,
298+
@NonNull FlutterJNI flutterJNI,
299+
@NonNull PlatformViewsController platformViewsController,
300+
@Nullable String[] dartVmArgs,
301+
boolean automaticallyRegisterPlugins,
302+
boolean waitForRestorationData,
303+
@Nullable FlutterEngineGroup group) {
282304
AssetManager assetManager;
283305
try {
284306
assetManager = context.createPackageContext(context.getPackageName(), 0).getAssets();
@@ -347,7 +369,8 @@ public FlutterEngine(
347369
this.platformViewsController.onAttachedToJNI();
348370

349371
this.pluginRegistry =
350-
new FlutterEngineConnectionRegistry(context.getApplicationContext(), this, flutterLoader);
372+
new FlutterEngineConnectionRegistry(
373+
context.getApplicationContext(), this, flutterLoader, group);
351374

352375
localizationPlugin.sendLocalesToFlutter(context.getResources().getConfiguration());
353376

shell/platform/android/io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@
9797
FlutterEngineConnectionRegistry(
9898
@NonNull Context appContext,
9999
@NonNull FlutterEngine flutterEngine,
100-
@NonNull FlutterLoader flutterLoader) {
100+
@NonNull FlutterLoader flutterLoader,
101+
@Nullable FlutterEngineGroup group) {
101102
this.flutterEngine = flutterEngine;
102103
pluginBinding =
103104
new FlutterPlugin.FlutterPluginBinding(
@@ -106,7 +107,8 @@
106107
flutterEngine.getDartExecutor(),
107108
flutterEngine.getRenderer(),
108109
flutterEngine.getPlatformViewsController().getRegistry(),
109-
new DefaultFlutterAssets(flutterLoader));
110+
new DefaultFlutterAssets(flutterLoader),
111+
group);
110112
}
111113

112114
public void destroy() {

shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroup.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ public void onEngineWillDestroy() {
210210
platformViewsController, // PlatformViewsController.
211211
null, // String[]. The Dart VM has already started, this arguments will have no effect.
212212
automaticallyRegisterPlugins, // boolean.
213-
waitForRestorationData); // boolean.
213+
waitForRestorationData, // boolean.
214+
this);
214215
}
215216

216217
/** Options that control how a FlutterEngine should be created. */

shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
import android.content.Context;
88
import androidx.annotation.NonNull;
9+
import androidx.annotation.Nullable;
910
import androidx.lifecycle.Lifecycle;
1011
import io.flutter.embedding.engine.FlutterEngine;
12+
import io.flutter.embedding.engine.FlutterEngineGroup;
1113
import io.flutter.plugin.common.BinaryMessenger;
1214
import io.flutter.plugin.platform.PlatformViewRegistry;
1315
import io.flutter.view.TextureRegistry;
@@ -107,20 +109,23 @@ class FlutterPluginBinding {
107109
private final TextureRegistry textureRegistry;
108110
private final PlatformViewRegistry platformViewRegistry;
109111
private final FlutterAssets flutterAssets;
112+
private final FlutterEngineGroup group;
110113

111114
public FlutterPluginBinding(
112115
@NonNull Context applicationContext,
113116
@NonNull FlutterEngine flutterEngine,
114117
@NonNull BinaryMessenger binaryMessenger,
115118
@NonNull TextureRegistry textureRegistry,
116119
@NonNull PlatformViewRegistry platformViewRegistry,
117-
@NonNull FlutterAssets flutterAssets) {
120+
@NonNull FlutterAssets flutterAssets,
121+
@Nullable FlutterEngineGroup group) {
118122
this.applicationContext = applicationContext;
119123
this.flutterEngine = flutterEngine;
120124
this.binaryMessenger = binaryMessenger;
121125
this.textureRegistry = textureRegistry;
122126
this.platformViewRegistry = platformViewRegistry;
123127
this.flutterAssets = flutterAssets;
128+
this.group = group;
124129
}
125130

126131
@NonNull
@@ -157,6 +162,11 @@ public PlatformViewRegistry getPlatformViewRegistry() {
157162
public FlutterAssets getFlutterAssets() {
158163
return flutterAssets;
159164
}
165+
166+
@Nullable
167+
public FlutterEngineGroup getEngineGroup() {
168+
return group;
169+
}
160170
}
161171

162172
/** Provides Flutter plugins with access to Flutter asset information. */

shell/platform/android/io/flutter/embedding/engine/plugins/shim/ShimPluginRegistry.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
*
2626
* <pre>
2727
* // Create the FlutterEngine that will back the Flutter UI.
28-
* FlutterEngine flutterEngine = new FlutterEngine(context);
28+
* FlutterEngineGroup group = new FlutterEngineGroup(context);
29+
* FlutterEngine flutterEngine = group.createAndRunDefaultEngine(context);
2930
*
3031
* // Create a ShimPluginRegistry and wrap the FlutterEngine with the shim.
3132
* ShimPluginRegistry shimPluginRegistry = new ShimPluginRegistry(flutterEngine, platformViewsController);

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

+17
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.Host;
3131
import io.flutter.embedding.engine.FlutterEngine;
3232
import io.flutter.embedding.engine.FlutterEngineCache;
33+
import io.flutter.embedding.engine.FlutterEngineGroup;
3334
import io.flutter.embedding.engine.FlutterShellArgs;
3435
import io.flutter.embedding.engine.dart.DartExecutor;
3536
import io.flutter.embedding.engine.loader.FlutterLoader;
@@ -1106,6 +1107,22 @@ public void itDoesNotDelayTheFirstDrawWhenRequestedAndWithAProvidedSplashScreen(
11061107
assertNull(delegate.activePreDrawListener);
11071108
}
11081109

1110+
@Test
1111+
public void usesFlutterEngineGroup() {
1112+
FlutterEngineGroup mockEngineGroup = mock(FlutterEngineGroup.class);
1113+
when(mockEngineGroup.createAndRunEngine(any(FlutterEngineGroup.Options.class)))
1114+
.thenReturn(mockFlutterEngine);
1115+
FlutterActivityAndFragmentDelegate.Host host =
1116+
mock(FlutterActivityAndFragmentDelegate.Host.class);
1117+
when(mockHost.getContext()).thenReturn(ctx);
1118+
1119+
FlutterActivityAndFragmentDelegate delegate =
1120+
new FlutterActivityAndFragmentDelegate(mockHost, mockEngineGroup);
1121+
delegate.onAttach(ctx);
1122+
FlutterEngine engineUnderTest = delegate.getFlutterEngine();
1123+
assertEquals(engineUnderTest, mockFlutterEngine);
1124+
}
1125+
11091126
/**
11101127
* Creates a mock {@link io.flutter.embedding.engine.FlutterEngine}.
11111128
*

shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineConnectionRegistryTest.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public void itDoesNotRegisterTheSamePluginTwice() {
4040
FakeFlutterPlugin fakePlugin2 = new FakeFlutterPlugin();
4141

4242
FlutterEngineConnectionRegistry registry =
43-
new FlutterEngineConnectionRegistry(context, flutterEngine, flutterLoader);
43+
new FlutterEngineConnectionRegistry(context, flutterEngine, flutterLoader, null);
4444

4545
// Verify that the registry doesn't think it contains our plugin yet.
4646
assertFalse(registry.has(fakePlugin1.getClass()));
@@ -86,7 +86,7 @@ public void activityResultListenerCanBeRemovedFromListener() {
8686

8787
// Set up the environment to get the required internal data
8888
FlutterEngineConnectionRegistry registry =
89-
new FlutterEngineConnectionRegistry(context, flutterEngine, flutterLoader);
89+
new FlutterEngineConnectionRegistry(context, flutterEngine, flutterLoader, null);
9090
FakeActivityAwareFlutterPlugin fakePlugin = new FakeActivityAwareFlutterPlugin();
9191
registry.add(fakePlugin);
9292
registry.attachToActivity(appComponent, lifecycle);
@@ -129,7 +129,7 @@ public void softwareRendering() {
129129

130130
// Test attachToActivity with an Activity that has no Intent.
131131
FlutterEngineConnectionRegistry registry =
132-
new FlutterEngineConnectionRegistry(context, flutterEngine, flutterLoader);
132+
new FlutterEngineConnectionRegistry(context, flutterEngine, flutterLoader, null);
133133
registry.attachToActivity(appComponent, mock(Lifecycle.class));
134134
verify(platformViewsController).setSoftwareRendering(false);
135135

shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineTest.java

+33
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525
import io.flutter.FlutterInjector;
2626
import io.flutter.embedding.engine.FlutterEngine;
2727
import io.flutter.embedding.engine.FlutterEngine.EngineLifecycleListener;
28+
import io.flutter.embedding.engine.FlutterEngineGroup;
2829
import io.flutter.embedding.engine.FlutterJNI;
2930
import io.flutter.embedding.engine.loader.FlutterLoader;
31+
import io.flutter.embedding.engine.plugins.FlutterPlugin;
32+
import io.flutter.embedding.engine.plugins.PluginRegistry;
3033
import io.flutter.plugin.platform.PlatformViewsController;
3134
import io.flutter.plugins.GeneratedPluginRegistrant;
3235
import java.util.List;
@@ -323,4 +326,34 @@ public void itComesWithARunningDartExecutorIfJNIIsAlreadyAttached() throws NameN
323326

324327
assertTrue(engineUnderTest.getDartExecutor().isExecutingDart());
325328
}
329+
330+
@Test
331+
public void passesEngineGroupToPlugins() throws NameNotFoundException {
332+
Context packageContext = mock(Context.class);
333+
334+
when(mockContext.createPackageContext(any(), anyInt())).thenReturn(packageContext);
335+
when(flutterJNI.isAttached()).thenReturn(true);
336+
337+
FlutterEngineGroup mockGroup = mock(FlutterEngineGroup.class);
338+
339+
FlutterEngine engineUnderTest =
340+
new FlutterEngine(
341+
mockContext,
342+
mock(FlutterLoader.class),
343+
flutterJNI,
344+
new PlatformViewsController(),
345+
/*dartVmArgs=*/ new String[] {},
346+
/*automaticallyRegisterPlugins=*/ false,
347+
/*waitForRestorationData=*/ false,
348+
mockGroup);
349+
350+
PluginRegistry registry = engineUnderTest.getPlugins();
351+
FlutterPlugin mockPlugin = mock(FlutterPlugin.class);
352+
ArgumentCaptor<FlutterPlugin.FlutterPluginBinding> pluginBindingCaptor =
353+
ArgumentCaptor.forClass(FlutterPlugin.FlutterPluginBinding.class);
354+
registry.add(mockPlugin);
355+
verify(mockPlugin).onAttachedToEngine(pluginBindingCaptor.capture());
356+
assertNotNull(pluginBindingCaptor.getValue());
357+
assertEquals(mockGroup, pluginBindingCaptor.getValue().getEngineGroup());
358+
}
326359
}

0 commit comments

Comments
 (0)