插件是flutter生态中必需品。开发者可以通过插件跟app所运行的平台进行交互。
在2018年的10月时,在 pub.dev上已经有上百款插件了。插件的质量尤为重要,不管插件是来自google官方还是第三方。本文主要是探索什么是一款好的插件以及如何打造。
功能性第一,其次才是APIs
很多时候在写插件时,桥接的是本地已经存在的库。最直接的做法就是根据原生库的api来写对应的dart api。但是当 APIs因为平台差异不太匹配时,你又不得不暴露更多的原生API细节,导致了很多坏结果。
当你书写插件时,优先考虑功能性,而不是APIs。比如,假设你在写一款本地存储插件,你可能需要的api是
- 能存各种类型的值
- 能够取到他们 想好你要支持的功能后,就可以思考你的dart api如何设计了:
class StoragePlugin {
/// Reads a string
Future<String> getString(String key) async {}
/// Writes a string
Future<void> setString(String key, String value) async {}
}
搞完这个,接下来开始关注对外暴露的API 和 如何进行平台适配:
class StoragePlugin {
Future<String> getString(String key) async {
if (Platform.isIos) {
return await callMethodChannel('fetchValue', {'id': base64encode(key)});
} else if (Platform.isAndroid) {
return await callMethodChannel('fetchValue', {'id': key});
}
}
Future<void> setString(String key, String value) async {
if (Platform.isIos) {
await callMethodChannel('setValue', {'id': base64encode(key), 'value': value});
} else if (Platform.isAndroid) {
await callMethodChannel('setValue', {'id': key, 'value': value});
}
}
}
如果你提供的某个功能不被某个平台支持,那API需要提供合理的报错信息。 可不能把app搞挂,而且这个不支持的操作应该是被注释出来。你应该继续请求platform来完成这个不支持的操作以走通整个插件调用流程。
避免特定平台的方法
Flutter本身是跨平台的,写特定平台的代码是不对滴。如果插件用户想做下面的事情:
if (Platform.isIos) {
myPlugin.doIOSThing();
} else if (Platform.isAndroid) {
myPlugin.doAndroidThing();
}
考虑将平台特定逻辑交给plugin本身完成,可以改成下面这样:
myPlugin.doThing();
避免仅支持一个平台
你可能一开始想写一个"小而美"的插件,功能仅支持Android。但是很不幸的是,当插件发布后,将会对不支持的平台用户即开发者造成困扰。
比如这款Android平台插件,Android Intent,如果不能显示,可以直接访问 github.com/flutter/plu…
让你的插件更容易被理解和测试
根据经验来说,你的插件应该包含较多的dart代码。
- native层很重要,主要是完成库在emulators不能起作用的功能。
- Flutter大部分是由dart书写的。Flutter app亦然,这样当你跟踪代码时,可以在dart里面自由跟进。
唯一使用native 层的原因应该是 平台相关实现需要保存状态或者其他一些处理。一个好的例子是 在Android上生物识别有着自己复杂的生命周期,这个需要native code来管理。
如果你需要写较多的native代码,考虑单一职权原则,划分到不同的类中方便单元测试。
理想情况下,你的插件仅仅是监听 方法调用,并把调用结果派发回dart端。如果你做的事情超过这个范围,试着看能否把多的部分移至dart端,最终你的代码逻辑会在多个平台进行复用,比如web 、Android、ios。
避免写静态( 或者全局)函数
比如:
Future<User> authenticate() async {
// Some code
}
但是下面的更好:
class AuthenticatePlugin {
Future<User> authenticate() async {
// Some code
}
}
这样会让插件更容易被mock。用户可以轻易替换掉真正的实现然后app可以运行在模拟器或者测试工具上。
最后
如果你看到了这里,觉得文章写得不错就给个赞呗!欢迎大家评论讨论!如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足,定期免费分享技术干货。感兴趣的小伙伴可以点一下关注哦。谢谢!
![](https://img.haomeiwen.com/i18813666/cab73c2915c87b8f.png)
网友评论