BaseOnFlutter2.0
public class FlutterEngineCache {
private static FlutterEngineCache instance;
private final Map<String, FlutterEngine> cachedEngines = new HashMap<>();
}
graph LR
FlutterApplication-->|after onCreate|flutterLoader.startInit-->similarToFlutter1.12
FlutterEngine-->initAssetManager
FlutterEngine-->initDartExecutor
FlutterEngine-->initMultipleChannels
FlutterEngine-->flutterLoader.startInitAndBlockUtilComplete
FlutterEngine-->flutterJNI.attachToNativeShell/Engine-->similarToFlutter1.12WhenConstuctFlutterView
FlutterEngine-->initFlutterRendererAndPlatformViewsController
FlutterEngine-->automaticallyRegisterPlugins
public FlutterEngine(@NonNull Context context, @Nullable String[] dartVmArgs) {
this(context, /* flutterLoader */ null, new FlutterJNI(), dartVmArgs, true);
}
/** Fully configurable {@code FlutterEngine} constructor. */
public FlutterEngine(
@NonNull Context context,
@Nullable FlutterLoader flutterLoader,
@NonNull FlutterJNI flutterJNI,
@NonNull PlatformViewsController platformViewsController,
@Nullable String[] dartVmArgs,
boolean automaticallyRegisterPlugins,
boolean waitForRestorationData) {
AssetManager assetManager;
try {
assetManager = context.createPackageContext(context.getPackageName(), 0).getAssets();
} catch (NameNotFoundException e) {
assetManager = context.getAssets();
}
this.dartExecutor = new DartExecutor(flutterJNI, assetManager);
this.dartExecutor.onAttachedToJNI();
DeferredComponentManager deferredComponentManager =
FlutterInjector.instance().deferredComponentManager();
accessibilityChannel = new AccessibilityChannel(dartExecutor, flutterJNI);
deferredComponentChannel = new DeferredComponentChannel(dartExecutor);
keyEventChannel = new KeyEventChannel(dartExecutor);
lifecycleChannel = new LifecycleChannel(dartExecutor);
localizationChannel = new LocalizationChannel(dartExecutor);
mouseCursorChannel = new MouseCursorChannel(dartExecutor);
navigationChannel = new NavigationChannel(dartExecutor);
platformChannel = new PlatformChannel(dartExecutor);
restorationChannel = new RestorationChannel(dartExecutor, waitForRestorationData);
settingsChannel = new SettingsChannel(dartExecutor);
systemChannel = new SystemChannel(dartExecutor);
textInputChannel = new TextInputChannel(dartExecutor);
if (deferredComponentManager != null) {
deferredComponentManager.setDeferredComponentChannel(deferredComponentChannel);
}
this.localizationPlugin = new LocalizationPlugin(context, localizationChannel);
this.flutterJNI = flutterJNI;
if (flutterLoader == null) {
flutterLoader = FlutterInjector.instance().flutterLoader();
}
if (!flutterJNI.isAttached()) {
flutterLoader.startInitialization(context.getApplicationContext());
flutterLoader.ensureInitializationComplete(context, dartVmArgs);
}
flutterJNI.addEngineLifecycleListener(engineLifecycleListener);
flutterJNI.setPlatformViewsController(platformViewsController);
flutterJNI.setLocalizationPlugin(localizationPlugin);
flutterJNI.setDeferredComponentManager(FlutterInjector.instance().deferredComponentManager());
// It should typically be a fresh, unattached JNI. But on a spawned engine, the JNI instance
// is already attached to a native shell. In that case, the Java FlutterEngine is created around
// an existing shell.
if (!flutterJNI.isAttached()) {
attachToJni();
}
// TODO(mattcarroll): FlutterRenderer is temporally coupled to attach(). Remove that coupling if
// possible.
this.renderer = new FlutterRenderer(flutterJNI);
this.platformViewsController = platformViewsController;
this.platformViewsController.onAttachedToJNI();
this.pluginRegistry =
new FlutterEngineConnectionRegistry(context.getApplicationContext(), this, flutterLoader);
if (automaticallyRegisterPlugins) {
registerPlugins();
}
}
/** System channel that sends Flutter navigation commands from Android to Flutter. */
@NonNull
public NavigationChannel getNavigationChannel() {
return navigationChannel;
}
public class NavigationChannel {
private static final String TAG = "NavigationChannel";
@NonNull public final MethodChannel channel;
public NavigationChannel(@NonNull DartExecutor dartExecutor) {
this.channel = new MethodChannel(dartExecutor, "flutter/navigation", JSONMethodCodec.INSTANCE);
}
public void setInitialRoute(@NonNull String initialRoute) {
Log.v(TAG, "Sending message to set initial route to '" + initialRoute + "'");
channel.invokeMethod("setInitialRoute", initialRoute);
}
public void pushRoute(@NonNull String route) {
Log.v(TAG, "Sending message to push route '" + route + "'");
channel.invokeMethod("pushRoute", route);
}
public void popRoute() {
Log.v(TAG, "Sending message to pop route.");
channel.invokeMethod("popRoute", null);
}
public void setMethodCallHandler(@Nullable MethodChannel.MethodCallHandler handler) {
channel.setMethodCallHandler(handler);
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
delegate = new FlutterActivityAndFragmentDelegate(this);
delegate.onAttach(this);//main
delegate.onRestoreInstanceState(savedInstanceState);
}
//FlutterActivityAndFragmentDelegate
void onAttach(@NonNull Context context) {
ensureAlive();
// When "retain instance" is true, the FlutterEngine will survive configuration
// changes. Therefore, we create a new one only if one does not already exist.
if (flutterEngine == null) {
setupFlutterEngine();
}
......
}
//FlutterActivityAndFragmentDelegate
/* package */ void setupFlutterEngine() {
// First, check if the host wants to use a cached FlutterEngine.
String cachedEngineId = host.getCachedEngineId();
if (cachedEngineId != null) {
flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId);
isFlutterEngineFromHost = true;
if (flutterEngine == null) {
throw new IllegalStateException(
"The requested cached FlutterEngine did not exist in the FlutterEngineCache: '"
+ cachedEngineId
+ "'");
}
return;
}
/**
* Returns the ID of a statically cached {@link FlutterEngine} to use within this {@code
* FlutterActivity}, or {@code null} if this {@code FlutterActivity} does not want to use a cached
* {@link FlutterEngine}.
*/
@Override
@Nullable
public String getCachedEngineId() {
return getIntent().getStringExtra(EXTRA_CACHED_ENGINE_ID);
}