导语:随着Flutter生态的快速发展,开发Flutter插件成为提高效率的关键。本文以native_image_view插件为例,详细介绍Flutter插件的开发流程,涵盖创建、开发、测试和发布等方面。
一、概述
主流的开发语言几乎都有自己的包管理工具,例如Node的npm、Android的Gradle,而Flutter也有Dart Packages仓库。插件的开发和复用能够提高开发效率,降低工程耦合度。对于网络请求、用户授权等常用功能,只需引入对应插件即可快速集成,从而专注于业务实现。在Flutter项目中,面对通用业务逻辑拆分或原生能力封装等场景,开发者仍需开发新组件。本文通过native_image_view插件,完整展示Flutter组件的开发和发布流程。
二、Flutter与Native通信
在Flutter插件开发中,经常需要进行Flutter与Native端的数据交互,因此需了解Platform Channel机制。这是一种C/S模型,Flutter作为Client,iOS和Android平台作为Host,Flutter通过该机制向Native发送消息,Native调用平台API实现后返回结果。
Platform Channel提供三种交互方式:
- BasicMessageChannel:用于传递字符串和半结构化信息。
- MethodChannel:用于传递方法调用和处理回调。
- EventChannel:用于数据流的监听与发送。
每种channel都包含三个重要成员变量:
- String name:表示channel的名字,应采用唯一命名标识,推荐使用组织名称加插件名称,例如com.tencent.game/native_image_view。
- BinaryMessager messager:作为Native与Flutter通信的载体,负责二进制数据的传递和handler映射。
- MessageCodec/MethodCodec codec:用于通信过程中的编解码,将基础类型编码为二进制或反向转换。
本文实现的native_image_view插件主要使用MethodChannel通信,Flutter将图片地址传递给原生侧,iOS和Android平台获取图片后转换为二进制返回。
三、插件创建
Flutter组件根据是否包含原生代码分为两种:
- Flutter Package(包):仅包含dart代码,用于特定功能封装,如网络请求的http包。
- Flutter Plugin(插件):除dart代码外,还包含Android和iOS平台的代码实现,常用于封装原生能力,如flutter_keyboard_visibility插件。
Flutter插件可以通过Android Studio或命令行创建。
1. 创建Dart包
使用--template=package声明创建只包含dart代码的package:
flutter create --template=package hello
lib目录存放package代码实现,pubspec.yaml文件声明依赖。
2. 创建Flutter插件
使用--template=plugin声明创建同时包含iOS和Android代码的plugin,并通过选项指定组织、iOS和Android开发语言:
flutter create --template=plugin --org com.tencent.game -i objc -a java native_image_view
相比Package,Plugin多出android、ios和example目录,用于平台代码实现和调试。
四、插件开发
Plugin和Package开发流程基本一致,但Plugin涉及iOS和Android开发,更复杂。本文开发native_image_view插件,将Flutter图片的下载和缓存交给Native实现,Flutter端仅负责绘制,同时通过特殊协议处理本地图片调用,解决图片复用问题。
1. Flutter端开发
在Flutter端声明MethodChannel,在initState方法中通过invokeMethod发起Native端调用,build方法中先显示打底图,待图片数据返回后使用Image.memory绘制图片:
class _NativeImageViewState extends State<NativeImageView> {
Uint8List _data;
static const MethodChannel _channel =
const MethodChannel('com.tencent.game/native_image_view');
@override
void initState() {
super.initState();
loadImageData();
}
loadImageData() async {
_data = await _channel.invokeMethod("getImage", {"url": widget.url});
setState(() {});
}
@override
Widget build(BuildContext context) {
return _data == null
? Container(
color: Colors.grey,
width: widget.width,
height: widget.height,
)
: Image.memory(
_data,
width: widget.width,
height: widget.height,
fit: BoxFit.cover,
);
}
}
2. Native端开发
(1)iOS开发
使用SDWebImage组件进行网络图片下载和缓存,在native_image_view.podspec文件中声明依赖。Flutter自动生成的NativeImageViewPlugin.m文件中,registerWithRegistrar方法作为组件入口,创建MethodChannel并处理Flutter端调用。handleMethodCall方法通过FlutterMethodCall获取方法名和参数,通过FlutterResult返回图片内容。
处理图片调用时,判断请求的是本地还是网络图片:本地图片直接读取二进制数据返回;网络图片先检查缓存,有缓存则返回,无缓存则下载后返回。
(2)Android开发
使用Glide组件进行网络图片下载和缓存,在build.gradle文件中声明依赖。插件在onAttachedToEngine和registerWith方法中实现MethodChannel注册与监听,onMethodCall处理Flutter方法调用。
实现逻辑与iOS一致:本地图片根据文件名获取Bitmap并转换为byte数组返回;网络图片通过Glide获取缓存或下载路径,读取文件为byte数组返回。
五、插件测试
Flutter脚手架创建的example项目通过指定插件path引用开发中的组件,便于测试和展示使用示例。main.dart中展示网络图片和本地图片的使用方式。
六、插件发布
插件开发完成后,在pubspec.yaml文件中填写仓库地址,运行dry-run命令检查发布要求。需注意删除废弃的author字段,并填写LICENSE文件中的开源协议。
1. 公共仓库
发布到公共仓库的插件将永久存在,不允许撤回。使用publish命令发布,过程中可能需登录谷歌账号验证。发布成功后,可在pub.dev搜索到插件。其他项目通过pubspec.yaml引用:
dependencies:
native_image_view: ^0.0.1
2. 私有仓库
对于内部使用,可搭建私有仓库。Flutter官方提供pub_server组件,快速搭建本地仓库服务器。配置dart环境后,安装并运行pub_server。在pubspec.yaml中新增publish_to字段指定私有仓库地址,发布时使用--server选项。引用私有仓库插件时,需在pubspec.yaml中通过hosted参数指定地址。
七、结语
本文介绍了Platform Channel机制,并通过native_image_view插件详细讲解了Flutter插件的创建、开发、测试和发布流程。封装通用功能为Flutter组件能提高项目可扩展性,减少耦合。希望本文能为Flutter插件开发提供帮助。
扩展阅读
- Flutter文档
- 闲鱼Flutter图片框架架构演进
- Flutter Pub私有仓库搭建
- Flutter实战图片组件演进之外接纹理解析
- Flutter插件开发需要了解的EventChannel与MethodChannel
- 如何开发Flutter平台channel