Flutter深入之插件新API——Embedding-V2

Flutter深入之插件新API——Embedding-V2

在Flutter1.12版本中正式将Embedding-V2API在Android平台默认开启,所有官方插件都迁移到了新的API。Embedding-V2APi的优势在于针对混合开发提供了更好的支持。

版本配置

GeneratedPluginRegistrant生成内容配置,通过在AndroidManifest.xml中配置Embedding的版本来确定工具生成的GeneratedPluginRegistrant类的内容。

1
2
3
4
5
<!-- Don't delete the meta-data below.
It is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />

具体判定逻辑在flutter_tools项目中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  AndroidEmbeddingVersion getEmbeddingVersion() {
if (isModule) {
// A module type's Android project is used in add-to-app scenarios and
// only supports the V2 embedding.
return AndroidEmbeddingVersion.v2;
}
if (appManifestFile == null || !appManifestFile.existsSync()) {
return AndroidEmbeddingVersion.v1;
}
xml.XmlDocument document;
try {
document = xml.parse(appManifestFile.readAsStringSync());
} on xml.XmlParserException {
throwToolExit('Error parsing $appManifestFile '
'Please ensure that the android manifest is a valid XML document and try again.');
} on FileSystemException {
throwToolExit('Error reading $appManifestFile even though it exists. '
'Please ensure that you have read permission to this file and try again.');
}
for (xml.XmlElement metaData in document.findAllElements('meta-data')) {
final String name = metaData.getAttribute('android:name');
if (name == 'flutterEmbedding') {
final String embeddingVersionString = metaData.getAttribute('android:value');
if (embeddingVersionString == '1') {
return AndroidEmbeddingVersion.v1;
}
if (embeddingVersionString == '2') {
return AndroidEmbeddingVersion.v2;
}
}
}
return AndroidEmbeddingVersion.v1;
}
}

创建时机变更

旧API

旧的创建插件的时机一般是在FlutterActivity的子类onCreate()回调时,手动调用下面的方法来创建所有的插件。

1
GeneratedPluginRegistrant.registerWith(PluginRegistry registry);

新API

新的API将插件与视图进行解绑,将插件与引擎进行绑定,并且在引擎创建的时候提供了自动创建插件的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public FlutterEngine(
@NonNull Context context,
@NonNull FlutterLoader flutterLoader,
@NonNull FlutterJNI flutterJNI,
@Nullable String[] dartVmArgs,
boolean automaticallyRegisterPlugins
) {

this.pluginRegistry = new FlutterEnginePluginRegistry(
context.getApplicationContext(),
this,
flutterLoader
);
// 默认为true,自动创建插件
if (automaticallyRegisterPlugins) {
registerPlugins();
}
}

// 通过反射调用GeneratedPluginRegistrant.registerWith(FlutterEngine engine)方法
private void registerPlugins() {
try {
Class<?> generatedPluginRegistrant = Class.forName("io.flutter.plugins.GeneratedPluginRegistrant");
Method registrationMethod = generatedPluginRegistrant.getDeclaredMethod("registerWith", FlutterEngine.class);
registrationMethod.invoke(null, this);
} catch (Exception e) {
Log.w(TAG, "Tried to automatically register plugins with FlutterEngine ("
+ this + ") but could not find and invoke the GeneratedPluginRegistrant.");
}
}

注册对象变更

旧API

在旧的API中,registerWith方法接收的参数类型是PluginRegistry。PluginRegistry(io.flutter.plugin.common包)维护所有的插件,每一个想注册的插件都通过pluginKey在PluginRegistry这里创建一个Registrar对象(内部类对象,提供外部类私有属性的公有方法),通过该对象,每个插件可以获取到全局的BinaryMessenger对象(也就是NativeView),通过该对象可以在插件中创建一个MethodChannel来进行插件通信。

Registrant

插件注册者,所有在pubspec.yaml中配置的插件都会自动在下面方法中生成。

1
2
3
4
5
6
7
8
9
10
public final class GeneratedPluginRegistrant {
public static void registerWith(PluginRegistry registry) {
if (alreadyRegisteredWith(registry)) {
return;
}
MartletVideoEditorPlugin.registerWith(registry.registrarFor("com.zhenyu.martlet/videoEditor"));
}

...
}

Registry

PluginRegistry对外的实现类是FlutterActivity(io.flutter.app包),最终的实现类是FlutterPluginRegistry。

FlutterPluginRegistry对象是由NativeView创建的,创建时机在FlutterActivity(io.flutter.app包)的onCreate时。

1
2
3
4
5
6
7
8
9
10
public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) {
mContext = context;
mPluginRegistry = new FlutterPluginRegistry(this, context);
mFlutterJNI = new FlutterJNI();
mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets());
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
attach(this, isBackgroundView);
assertAttached();
}

在Registry中维护了一个插件map,里面包含了所有注册的插件。

1
private final Map<String, Object> mPluginMap = new LinkedHashMap<>(0);

注册pluginKey,获取Registrar

1
2
3
4
5
6
7
8
@Override
public Registrar registrarFor(String pluginKey) {
if (mPluginMap.containsKey(pluginKey)) {
throw new IllegalStateException("Plugin key " + pluginKey + " is already in use");
}
mPluginMap.put(pluginKey, null);
return new FlutterRegistrar(pluginKey);
}

Registrar

Registrar只是一个内部类对象,提供Registry的一些私有属性暴露给外部使用,其中最重要的就是暴露BinaryMessenger对象给插件对象使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private class FlutterRegistrar implements Registrar {
private final String pluginKey;

FlutterRegistrar(String pluginKey) {
this.pluginKey = pluginKey;
}

@Override
public Activity activity() {
return mActivity;
}

@Override
public BinaryMessenger messenger() {
return mNativeView;
}

@Override
public TextureRegistry textures() {
return mFlutterView;
}

...
}

新API

在新API中,registerWith方法接收的参数是FlutterEngine。PluginRegistry(io.flutter.embedding.engine.plugins包)维护所有的插件,每一个想注册的插件都必须实现FlutterPlugin接口,并将自身对象添加到PluginRegistry(io.flutter.embedding.engine.plugins包)中。由PluginRegistry(io.flutter.embedding.engine.plugins包)统一操控所有插件的生命周期。

Registrant

插件注册者,所有在pubspec.yaml中配置的插件都会自动在下面方法中生成。

1
2
3
4
5
public final class GeneratedPluginRegistrant {
public static void registerWith(@NonNull FlutterEngine flutterEngine) {
flutterEngine.getPlugins().add(new com.zhenyu.martlet.core_flutter.MartletVideoEditorPlugin());
}
}

Registry

在FlutterEngine创建的时候,就会创建一个FlutterEnginePluginRegistry对象,来维护所有的插件,flutterEngine.getPlugins()获取的就是FlutterEnginePluginRegistry对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public FlutterEngine(
@NonNull Context context,
@NonNull FlutterLoader flutterLoader,
@NonNull FlutterJNI flutterJNI,
@Nullable String[] dartVmArgs,
boolean automaticallyRegisterPlugins
) {

this.pluginRegistry = new FlutterEnginePluginRegistry(
context.getApplicationContext(),
this,
flutterLoader
);
// 默认为true,自动创建插件
if (automaticallyRegisterPlugins) {
registerPlugins();
}
}

在Registry中维护了一个插件map,里面包含了所有注册的插件对象的实例。

1
private final Map<Class<? extends FlutterPlugin>, FlutterPlugin> plugins = new HashMap<>();

添加插件对象实例,触发插件的各种生命周期方法,并将插件需要的BinaryMessenger对象通过生命周期方法传递给插件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@Override
public void add(@NonNull FlutterPlugin plugin) {
// 将插件实例添加到map中维护
plugins.put(plugin.getClass(), plugin);
// 调用插件的onAttachedToEngine方法,pluginBinding参数中包含了需要的BinaryMessenger对象。
plugin.onAttachedToEngine(pluginBinding);

// 如果插件实现了ActivityAware接口,触发Activity生命周期方法
if (plugin instanceof ActivityAware) {
ActivityAware activityAware = (ActivityAware) plugin;
activityAwarePlugins.put(plugin.getClass(), activityAware);

if (isAttachedToActivity()) {
activityAware.onAttachedToActivity(activityPluginBinding);
}
}

// 如果插件实现了ServiceAware接口,触发Service生命周期方法
if (plugin instanceof ServiceAware) {
ServiceAware serviceAware = (ServiceAware) plugin;
serviceAwarePlugins.put(plugin.getClass(), serviceAware);

if (isAttachedToService()) {
serviceAware.onAttachedToService(servicePluginBinding);
}
}

// 如果插件实现了BroadcastReceiverAware接口,触发BroadcastReceiver生命周期方法
if (plugin instanceof BroadcastReceiverAware) {
BroadcastReceiverAware broadcastReceiverAware = (BroadcastReceiverAware) plugin;
broadcastReceiverAwarePlugins.put(plugin.getClass(), broadcastReceiverAware);

if (isAttachedToBroadcastReceiver()) {
broadcastReceiverAware.onAttachedToBroadcastReceiver(broadcastReceiverPluginBinding);
}
}

// 如果插件实现了ContentProviderAware接口,触发ContentProvider生命周期方法
if (plugin instanceof ContentProviderAware) {
ContentProviderAware contentProviderAware = (ContentProviderAware) plugin;
contentProviderAwarePlugins.put(plugin.getClass(), contentProviderAware);

if (isAttachedToContentProvider()) {
contentProviderAware.onAttachedToContentProvider(contentProviderPluginBinding);
}
}
}

插件实现变更

旧API

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MartletVideoEditorPlugin implements MethodChannel.MethodCallHandler {
static MethodChannel mChannel;

public static void registerWith(PluginRegistry.Registrar registrar) {
mChannel = new MethodChannel(registrar.messenger(), "com.zhenyu.martlet/videoEditor");
mChannel.setMethodCallHandler(this);
}

@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {

}
}

新API

插件只需实现FlutterPlugin接口,然后在onAttachedToEngine方法中创建MethodChannel,并设置MethodCallHandler,在onDetachedFromEngine方法中将释放MethodChannel。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MartletVideoEditorPlugin implements FlutterPlugin, MethodCallHandler {

private MethodChannel mChannel;

@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
mChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "com.zhenyu.martlet/videoEditor");
mChannel.setMethodCallHandler(this);
}

// 如果插件不兼容旧API,可以忽略该方法的现实
public static void registerWith(Registrar registrar) {
}

@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {

}

@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
mChannel.setMethodCallHandler(null);
mChannel = null;
}

}

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×