io.flutter.embedding.android.FlutterActivity(如无特殊说明,下文中的FlutterActivity单指此包下的类。)重写了android.app.Activity中的onCreate方法:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//...
setContentView(createFlutterView());
//...
}
再来看一下方法createFlutterView()的源码:
@NonNull
private View createFlutterView() {
return delegate.onCreateView(null,null,null,FLUTTER_VIEW_ID,getRenderMode() == RenderMode.surface);
}
可以看到,这里调用了一个delegate的onCreateView(…)方法。这个变量delegate是什么东西?在哪里被设值了?可以变更吗?它是FlutterActivity中的一个变量:
protected FlutterActivityAndFragmentDelegate delegate;
它在onCreate方法中被初始化了:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//...
delegate = new FlutterActivityAndFragmentDelegate(this);
//...
setContentView(createFlutterView());
//...
}
接着看一下这个delegate的onCreateView(…)方法的源码:
@NonNull
View onCreateView(
LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState,
int flutterViewId,
boolean shouldDelayFirstAndroidViewDraw) {
//...
flutterView.attachToFlutterEngine(flutterEngine);
//...
}
大致意思就是把flutterView attach到FlutterEngine(Flutter引擎)上去,并且提供了一个引擎对象flutterEngine。FlutterEngine是什么?简单地说,它使得在Android Application中执行Dart成为可能。再简单点说,它就是一个黑盒子,里面在执行Dart代码。至于它到底还干了什么别的,具体怎么干的?我也不知道。
接下来找找看这个引擎对象是如何被初始化的。
class FlutterActivityAndFragmentDelegate implements ... {
@Nullable private FlutterEngine flutterEngine;
void setupFlutterEngine() {
//...
// First, check if the host wants to use a cached FlutterEngine.
//...
// Second, defer to subclasses for a custom FlutterEngine.
//...
// Our host did not provide a custom FlutterEngine. Create a FlutterEngine to back our
// FlutterView.
//...
}
}
源码注释的大致意思应该是:第一步,缓存的引擎用不用?用就返回。第二步,子类有没有提供自己的引擎?有就返回。第三步,创建一个,并返回。这里暂且不管它的引擎缓存机制是如何实现的,也不管它的子类提供引擎的机制是什么,先看一下它是如何被创建出来的。
void setupFlutterEngine() {
//...
flutterEngine = new FlutterEngine(
host.getContext(),
host.getFlutterShellArgs().toArray(),
false,
host.shouldRestoreAndSaveState());
//...
}
只是调了一个构造而已嘛!没什么大不了的。当我们仔细地观察会发现,所有构造器最后都指向同一个构造器,即
public FlutterEngine(
@NonNull Context context,
@Nullable FlutterLoader flutterLoader,
@NonNull FlutterJNI flutterJNI,
@NonNull PlatformViewsController platformViewsController,
@Nullable String[] dartVmArgs,
boolean automaticallyRegisterPlugins,
boolean waitForRestorationData)
此处,我们暂且不关注该构造器的具体实现,只看该方法的最后几行代码,如下所示:
//...
if (automaticallyRegisterPlugins && flutterLoader.automaticallyRegisterPlugins()) {
GeneratedPluginRegister.registerGeneratedPlugins(this);
}
public static void registerGeneratedPlugins(@NonNull FlutterEngine flutterEngine) {
try {
Class<?> generatedPluginRegistrant =
Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method registrationMethod =
generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
registrationMethod.invoke(null, flutterEngine);
} catch (Exception e) {
Log.e(
TAG,
"Tried to automatically register plugins with FlutterEngine ("
+ flutterEngine
+ ") but could not find or invoke the GeneratedPluginRegistrant.");
Log.e(TAG, "Received exception while registering", e);
}
}
这是一段极为普通的反射代码,它执行了类io.flutter.plugins.GeneratedPluginRegistrant
的方法registerWith
,是不是非常眼熟了?在我们的Flutter APP中android文件夹下就有一个自动生成的类与之同名,即
public final class GeneratedPluginRegistrant {
private static final String TAG = "GeneratedPluginRegistrant";
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
//...
}
}
现在我们知道了,当引擎被构造时,就会去注册插件。那么除了这一时机之外,还会有其它时机注册插件吗?
FlutterActivity类有代码如下所示:
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
//...
GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//...
delegate = new FlutterActivityAndFragmentDelegate(this);
delegate.onAttach(this);
//...
setContentView(createFlutterView());
//...
}
FlutterFragmentActivity类有代码如下所示:
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
//...
GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine);
}
FlutterActivityAndFragmentDelegate类有代码如下所示:
void onAttach(@NonNull Context context) {
//...
if