写点什么

前端技术:一文带你掌握 Flutter 插件开发新姿势

2021 年 5 月 05 日

前端技术:一文带你掌握Flutter插件开发新姿势

概述


随着开发技术的发展,几乎所有主流的开发语言都有自己的包管理工具。Node 开发有 npm、Android 开发有 Gradle,Flutter 也有自己的 Dart Packages 仓库。插件的开发和复用能够提高开发效率,降低工程的耦合度,像网络请求(http)、用户授权(permission_handler)等客户端开发常用的功能模块,我们只需要引入对应插件就可以为项目快速集成相关能力,从而专注于具体业务功能的实现。


除了使用仓库中的流行组件以外,在 Flutter 项目开发过程中面对通用业务逻辑拆分、或者需要对原生能力封装等场景时,开发者仍然需要开发新的组件。本文以一个具体的 native_image_view 插件为例,将从 Flutter 组件的创建、开发、测试和发布等多个方面进行介绍,力图完整的展示整个 Flutter 组件的开发和发布流程。


Flutter 与 Native 通信


在 Flutter 插件开发过程中,几乎都会需要进行 Flutter 与 Native 端的数据交互,因此在进行插件开发之前,我们先简单了解下 Platform Channel 机制


Flutter 与 Native 的通信是通过 Platform Channel 实现的,它是一种 C/S 模型,其中 Flutter 作为 Client,iOS 和 Android 平台作为 Host,Flutter 通过该机制向 Native 发送消息,Native 在收到消息后调用平台自身的 API 进行实现,然后将处理结果再返回给 Flutter 页面。



Flutter 中的 Platform Channel 机制提供了三种交互方式:


  • BasicMessageChannel :用于传递字符串和半结构化信息;

  • MethodChannel :用于传递方法调用和处理回调;

  • EventChannel:用于数据流的监听与发送。


这三种 channel 虽然用途不同,但都包含了三个重要的成员变量:


(1)String name


表示 channel 的名字,在一个项目中可能会有很多的 channel,每个 channel 都应该使用唯一的命名标识,否则可能会被覆盖。推荐的命名方式是组织名称加插件的名称,例如:com.tencent.game/native_image_view,如果一个插件中包含了多个 channel 可再根据功能模块进一步进行区分。


(2)BinaryMessager messager


作为 Native 与 Flutter 通信的载体,能够将 codec 转换后的二进制数据在 Native 与 Flutter 之间进行传递。每个 channel 在初始化时都要生成或提供对应的 messager,如果 channel 注册了对应的 handler,则 messager 会维护一个 name 与 handler 的映射关系。


Native 平台在收到对方发来的消息后,meesager 会将消息内容分发给对应的 handler 进行处理,在处理完成后还可以通过回调方法 result 将处理结果返回给 Flutter。



(3)MessageCodec/MethodCodec codec


用于 Native 与 Flutter 通信过程中的编解码,在发送方能够将 Flutter(或 Native)的基础类型编码为二进制进行数据传输,在接收方 Native(或 Flutter)将二进制转换为 handler 能够识别的基础类型。


注:本文实现的 native_image_share 插件仅用到了最为常用的 MethodChannel 通信,Flutter 通过 MethodChannel 将远程图片地址或本地图片文件名传递给原生侧,iOS 和 Android 平台获取到图片后转换为二进制并通过 result 返回。更多关于 MessageChannel 和 EventChannel 的示例可以文末提供参考扩展阅读。


插件创建


Flutter 组件根据是否包含原生代码可分为两种:


  • Flutter Package(包):仅包含 dart 代码,一般是对 flutter 特定功能的封装实现,例如用于网络请求的 http 包。

  • Flutter Plugin(插件):除了 dart 代码之外,还包含了 Android 和 iOS 平台的代码实现,常用于将客户端原生的能力进行封装,然后提供给 flutter 项目使用。例如用于判断键盘可见状态的 flutter_keyboard_visibility 插件,就是分别在 iOS 和 Android 端监听了键盘的打开和关闭事件,然后将对应事件通过 Platform Channel 传递给 Flutter 项目。



Flutter 插件可以通过 Android Studio 创建(需要在 Android Studio 中先安装 Dart 和 Flutter 插件),或者使用命令行创建。


1. 创建 Dart 包


使用--template=package 声明创建的是只包含 dart 代码的 package。


flutter create --template=package hello
复制代码



lib 目录用于存放 package 的代码实现,Flutter 脚手架会自动生成一个与 package 同名的 dart 文件。

pubspec.yaml 文件想必做过 Flutter 开发的同学都非常熟悉,我们开发 package 所依赖的 package 或者 plugin 都需要在该文件中声明。


2. 创建 Flutter 插件


  • 使用--template=plugin 声明创建的是同时包含了 iOS 和 Android 代码的 plugin;

  • 使用--org 选项指定组织,一般采用反向域名表示法;

  • 使用-i 选项指定 iOS 平台开发语言,objc 或者 swift;

  • 使用-a 选项指定 Android 平台开发语言,java 或者 kotlin。

flutter create --template=plugin --org com.tencent.game -i objc -a java native_image_view
复制代码



相比 Package,我们可以看到 Plugin 多出了一些目录,android 目录用于 Android 平台的代码实现,ios 目录用于 iOS 平台的代码实现,example 目录用于该组件的调试。


注:Flutter 脚手架在创建 Plugin 时默认实现了一个获取系统版本号的示例,该示例的原理是分别在 iOS 和 Android 平台获取到系统版本号,然后通过 MethodChannel 调用返回给 Flutter 平台显示。


插件开发


Plugin 和 Package 的开发和发布流程基本一致,相比之下 Plugin 还涉及到 iOS 和 Android 的开发,实现起来要更加复杂一些。


在 Flutter 嵌入原生项目的场景中,比较常见的一个问题是:Flutter 和原生项目中都使用了同一张图片时,两侧会分别进行存储,即该图片会被存储两次。不同于 Weex、Hippy 等基于 JS 的跨平台框架是依赖于原生进行图片的获取和显示,Flutter 是自行进行图片的管理并直接通过 Skia 引擎直接进行绘制的。


针对这一问题,本文将开发一个 Flutter 插件(native_image_view),把 Flutter 图片的下载和缓存工作交给 Native 实现,Flutter 端则仅负责图片的绘制。此外,我们还可以定义一个特殊协议,用于处理本地图片的调用,同时解决 Flutter 无法复用原生项目本地图片的问题。



注:本文开发的插件仅用于介绍插件的开发和发布流程,不建议在生成环境中直接使用,关于图片二次缓存问题还可以参考扩展阅读中关于 Texture(外接纹理)的文章。


头图:Unsplash

作者:赵哲

原文:https://mp.weixin.qq.com/s/mRXDKvyj_3pDjxM_axTDmQ

原文:前端技术:一文带你掌握 Flutter 插件开发新姿势

来源:云加社区 - 微信公众号 [ID:QcloudCommunity]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021 年 5 月 05 日 07:072443

评论

发布
暂无评论
发现更多内容

第三周作业

王鑫龙

极客大学架构师训练营

架构师训练营作业 --Week3

吴炳华

极客大学架构师训练营

分布式时序数据库SilverDB-技术架构1

Hervor。

时序数据库 分布式架构 分布式存储

架构师训练营 - 第三周 - 学习总结

韩挺

看完这篇 HashMap,和面试官扯皮就没问题了

cxuan

Java 源码分析

week03 单例作业以及组合模式

李锦

极客大学架构师训练营

架构师训练营 - 第三课作业 -20200624- 单例及组合模式

👑👑merlan

架构设计 极客大学架构师训练营

Linux性能优化实战-第一天学习

程序员老王

c++ 性能调优

架构师训练营第三章作业

叮叮董董

Zookeeper面试题36问,再和面试官多聊半个点

Java小咖秀

zookeeper 负载均衡 分布式协同 面试题 分布式系统

观察者模式详解

七哥爱编程

设计模式 观察者模式

为什么建议你使用枚举?

王磊

Java 枚举

架构师训练营 - 第三周 - 作业

韩挺

锦囊篇|一文摸懂Glide

ClericYi

漫画通信:有了它,终于可以放心买买买了

阿里云Edge Plus

云通信 短信 语音 通信云

读懂一个 demo,入门机器学习

陈东泽 EuryChen

人工智能 tensorflow 学习 AI

架构师训练营 - 作业 - 第三周

心在飞

极客大学架构师训练营

如何学习设计模式

elfkingw

极客大学架构师训练营

架构师训练营-第三周作业

清风徐徐

架构训练营第三章课后作业单例模式 组合模式

周冬辉

BIGO全球计算平台的技术挑战

DT极客

设计模式与敏捷开发

架构师 架构是训练营

架构师训练营第三章总结

叮叮董董

第三周作业

CP

代码重构:如何充实你的设计工具箱

WANDEFOUR

极客大学架构师训练营 代码重构

【架构师训练营】第三周总结

Mr.hou

极客大学架构师训练营

架构师训练营第三周作业

大丁💸💵💴💶🚀🐟

投资人李丰对中国商业模式创新的理解

石云升

投资 零售 模式创新

改变要一点点来

Neco.W

正确阅读 进步

架构师训练营 No.3 周作业

连增申

【架构师训练营】第三周作业

Mr.hou

极客大学架构师训练营

技术为帆,纵横四海- Lazada技术东南亚探索和成长之旅

技术为帆,纵横四海- Lazada技术东南亚探索和成长之旅

前端技术:一文带你掌握Flutter插件开发新姿势-InfoQ