未验证 提交 fad9ae8e 编写于 作者: X xster 提交者: GitHub

Load FlutterLoader when creating FlutterEngineGroup (#23980)

上级 f6280f26
...@@ -8,7 +8,9 @@ import android.content.Context; ...@@ -8,7 +8,9 @@ import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import io.flutter.FlutterInjector;
import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint; import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint;
import io.flutter.embedding.engine.loader.FlutterLoader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -25,6 +27,9 @@ import java.util.List; ...@@ -25,6 +27,9 @@ import java.util.List;
* io.flutter.embedding.engine.FlutterEngine}s are created, resources from an existing living {@link * io.flutter.embedding.engine.FlutterEngine}s are created, resources from an existing living {@link
* io.flutter.embedding.engine.FlutterEngine} is re-used. * io.flutter.embedding.engine.FlutterEngine} is re-used.
* *
* <p>The shared resources are kept until the last surviving {@link
* io.flutter.embedding.engine.FlutterEngine} is destroyed.
*
* <p>Deleting a FlutterEngineGroup doesn't invalidate its existing {@link * <p>Deleting a FlutterEngineGroup doesn't invalidate its existing {@link
* io.flutter.embedding.engine.FlutterEngine}s, but it eliminates the possibility to create more * io.flutter.embedding.engine.FlutterEngine}s, but it eliminates the possibility to create more
* {@link io.flutter.embedding.engine.FlutterEngine}s in that group. * {@link io.flutter.embedding.engine.FlutterEngine}s in that group.
...@@ -33,6 +38,23 @@ public class FlutterEngineGroup { ...@@ -33,6 +38,23 @@ public class FlutterEngineGroup {
/* package */ @VisibleForTesting final List<FlutterEngine> activeEngines = new ArrayList<>(); /* package */ @VisibleForTesting final List<FlutterEngine> activeEngines = new ArrayList<>();
/** Create a FlutterEngineGroup whose child engines will share resources. */
public FlutterEngineGroup(@NonNull Context context) {
this(context, null);
}
/**
* Create a FlutterEngineGroup whose child engines will share resources. Use {@code dartVmArgs} to
* pass flags to the Dart VM during initialization.
*/
public FlutterEngineGroup(@NonNull Context context, @Nullable String[] dartVmArgs) {
FlutterLoader loader = FlutterInjector.instance().flutterLoader();
if (!loader.initialized()) {
loader.startInitialization(context.getApplicationContext());
loader.ensureInitializationComplete(context, dartVmArgs);
}
}
/** /**
* Creates a {@link io.flutter.embedding.engine.FlutterEngine} in this group and run its {@link * Creates a {@link io.flutter.embedding.engine.FlutterEngine} in this group and run its {@link
* io.flutter.embedding.engine.dart.DartExecutor} with a default entrypoint of the "main" function * io.flutter.embedding.engine.dart.DartExecutor} with a default entrypoint of the "main" function
...@@ -67,18 +89,13 @@ public class FlutterEngineGroup { ...@@ -67,18 +89,13 @@ public class FlutterEngineGroup {
public FlutterEngine createAndRunEngine( public FlutterEngine createAndRunEngine(
@NonNull Context context, @Nullable DartEntrypoint dartEntrypoint) { @NonNull Context context, @Nullable DartEntrypoint dartEntrypoint) {
FlutterEngine engine = null; FlutterEngine engine = null;
// This is done up here because an engine needs to be created first in order to be able to use
// DartEntrypoint.createDefault. The engine creation initializes the FlutterLoader so
// DartEntrypoint known where to find the assets for the AOT or kernel code.
if (activeEngines.size() == 0) {
engine = createEngine(context);
}
if (dartEntrypoint == null) { if (dartEntrypoint == null) {
dartEntrypoint = DartEntrypoint.createDefault(); dartEntrypoint = DartEntrypoint.createDefault();
} }
if (activeEngines.size() == 0) { if (activeEngines.size() == 0) {
engine = createEngine(context);
engine.getDartExecutor().executeDartEntrypoint(dartEntrypoint); engine.getDartExecutor().executeDartEntrypoint(dartEntrypoint);
} else { } else {
engine = activeEngines.get(0).spawn(context, dartEntrypoint); engine = activeEngines.get(0).spawn(context, dartEntrypoint);
......
...@@ -8,12 +8,17 @@ import static org.junit.Assert.assertEquals; ...@@ -8,12 +8,17 @@ import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any; import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import io.flutter.embedding.engine.dart.DartExecutor; import android.content.res.AssetManager;
import io.flutter.FlutterInjector;
import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint; import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint;
import io.flutter.embedding.engine.loader.FlutterLoader; import io.flutter.embedding.engine.loader.FlutterLoader;
import io.flutter.plugins.GeneratedPluginRegistrant; import io.flutter.plugins.GeneratedPluginRegistrant;
...@@ -27,34 +32,41 @@ import org.robolectric.RobolectricTestRunner; ...@@ -27,34 +32,41 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
// It's a component test because it tests both FlutterEngineGroup and FlutterEngine. // It's a component test because it tests the FlutterEngineGroup its components such as the
// FlutterEngine and the DartExecutor.
@Config(manifest = Config.NONE) @Config(manifest = Config.NONE)
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class FlutterEngineGroupComponentTest { public class FlutterEngineGroupComponentTest {
@Mock FlutterJNI flutterJNI; @Mock FlutterJNI mockflutterJNI;
@Mock FlutterLoader mockFlutterLoader;
FlutterEngineGroup engineGroupUnderTest; FlutterEngineGroup engineGroupUnderTest;
FlutterEngine firstEngineUnderTest; FlutterEngine firstEngineUnderTest;
boolean jniAttached; boolean jniAttached;
@Before @Before
public void setUp() { public void setUp() {
FlutterInjector.reset();
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
jniAttached = false; jniAttached = false;
when(flutterJNI.isAttached()).thenAnswer(invocation -> jniAttached); when(mockflutterJNI.isAttached()).thenAnswer(invocation -> jniAttached);
doAnswer(invocation -> jniAttached = true).when(flutterJNI).attachToNative(false); doAnswer(invocation -> jniAttached = true).when(mockflutterJNI).attachToNative(false);
GeneratedPluginRegistrant.clearRegisteredEngines(); GeneratedPluginRegistrant.clearRegisteredEngines();
when(mockFlutterLoader.findAppBundlePath()).thenReturn("some/path/to/flutter_assets");
FlutterInjector.setInstance(
new FlutterInjector.Builder().setFlutterLoader(mockFlutterLoader).build());
firstEngineUnderTest = firstEngineUnderTest =
spy( spy(
new FlutterEngine( new FlutterEngine(
RuntimeEnvironment.application, RuntimeEnvironment.application,
mock(FlutterLoader.class), mock(FlutterLoader.class),
flutterJNI, mockflutterJNI,
/*dartVmArgs=*/ new String[] {}, /*dartVmArgs=*/ new String[] {},
/*automaticallyRegisterPlugins=*/ false)); /*automaticallyRegisterPlugins=*/ false));
when(firstEngineUnderTest.getDartExecutor()).thenReturn(mock(DartExecutor.class));
engineGroupUnderTest = engineGroupUnderTest =
new FlutterEngineGroup() { new FlutterEngineGroup(RuntimeEnvironment.application) {
@Override @Override
FlutterEngine createEngine(Context context) { FlutterEngine createEngine(Context context) {
return firstEngineUnderTest; return firstEngineUnderTest;
...@@ -127,4 +139,21 @@ public class FlutterEngineGroupComponentTest { ...@@ -127,4 +139,21 @@ public class FlutterEngineGroupComponentTest {
RuntimeEnvironment.application, mock(DartEntrypoint.class)); RuntimeEnvironment.application, mock(DartEntrypoint.class));
assertEquals(2, engineGroupUnderTest.activeEngines.size()); assertEquals(2, engineGroupUnderTest.activeEngines.size());
} }
@Test
public void canCreateAndRunCustomEntrypoints() {
FlutterEngine firstEngine =
engineGroupUnderTest.createAndRunEngine(
RuntimeEnvironment.application,
new DartEntrypoint(
FlutterInjector.instance().flutterLoader().findAppBundlePath(),
"other entrypoint"));
assertEquals(1, engineGroupUnderTest.activeEngines.size());
verify(mockflutterJNI, times(1))
.runBundleAndSnapshotFromLibrary(
eq("some/path/to/flutter_assets"),
eq("other entrypoint"),
isNull(String.class),
any(AssetManager.class));
}
} }
...@@ -14,7 +14,7 @@ public class SpawnedEngineActivity extends TestActivity { ...@@ -14,7 +14,7 @@ public class SpawnedEngineActivity extends TestActivity {
@Override @Override
public FlutterEngine provideFlutterEngine(@NonNull Context context) { public FlutterEngine provideFlutterEngine(@NonNull Context context) {
FlutterEngineGroup engineGroup = new FlutterEngineGroup(); FlutterEngineGroup engineGroup = new FlutterEngineGroup(context);
engineGroup.createAndRunDefaultEngine(context); engineGroup.createAndRunDefaultEngine(context);
FlutterEngine secondEngine = engineGroup.createAndRunDefaultEngine(context); FlutterEngine secondEngine = engineGroup.createAndRunDefaultEngine(context);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册