颤动混编方案在起点客户端的实践之路
作者:访客发布时间:2023-12-13分类:程序开发学习浏览:79
起点读书客户端一直紧跟新技术的潮流,从很早开始,就在进行Ffltter的尝试,在筹备了许久之后(移除了包大小的Kpi指标),我们终于在最新的业务开发中,使用了Fflighter。
颤动虽然会带来一些包体积的增加,但带来的收益却是:
- 愉悦的开发体验,不用再忍受漫长的编译,强大的热更新可以快速进行UI开发
- 跨端的统一UI设计,双端不用做太多的适配就可以运行
- 开发效率提升一倍以上,同时也提升设计和测试的效率
千呼万唤始出来,让我们来看下起点读书客户端是如何进行Ffltter混编开发的。
轻量化引擎架构
由于起点读书客户端目前依然是以原生开发为主,所以我们在嵌入Ffltter模块时,首先要考虑的就是使用哪种混合栈方案。目前市面上常见的混合栈方案,主要就是两种:一种是以颤振助推为例的单引擎方案,另一种是以引擎集团来实现的多引擎方案。这两种混合栈的方案,各有一些优缺点.
优势 | 劣势 | |
---|---|---|
单引擎混合栈 | 与本地独立开来,对本地的依赖最小,混编开发流程清晰、方便 | 混编存在混合栈内存泄漏等问题,会存在一些底层的CRASH;Ffltter和Native端都需要独立实现一套完整的网络和基础库等基础模块 |
多引擎混合栈 | 相比单引擎方案,性能更好,在多实例下内存压力更小,开发更加简便 | 对本地依赖大,多实例之间数据无法共享,需要从本地进行转发 |
我们在这两种架构方案的基础上,各取所长,提出了一套轻量化的引擎架构.
首先,我们采用的是Engine Group的混合栈方案,这个方案对于小规模嵌入Ffltter页面的NativeApp来说,是性价比最高的选择,它的技术架构如下所示。
但是和传统的Ffltter开发方案又有所不同,我们将Ffltter页面当作一个渲染容器,在一个Ffltter页面中,所有的数据都来源于本机、Ffltter只作渲染UI和处理交互逻辑,这种方案和之前的方案进行对比,结果如下。
优势 | 劣势 | |
---|---|---|
轻量化引擎方案 | 颤动端极其轻量,极大化利用颤动高效开发用户界面的优势 | 数据依赖原生、存在双向通信、原生需要作一些额外的处理 |
在这种轻量化的架构方案下,我们作了一些改进:
- Ffltter只作UI渲染,网络请求、基础数据等内容,都通过Native桥接,最大化的复用了Native的已有能力、Ffltter端不用重新复刻一套,同时,对于UI上的异常,可以很方便的进行处理,避免在Ffltter中使用网络库等能力时带来的新异常
- 抛弃颤动端常规的路由概念,将业务页面封装为独立的方案、类似本地中的动作Url、简化调用逻辑
- 通过搭建一套数据Mock的方式,在Ffltter端进行开发,避免在开发阶段,需要从本地获取数据的问题
综上所述,经过多方面的考虑和调整,最终确定了当前起点读书Ffltter的架构方案。
在当前架构下、本地端需要实现一套通用的频道协议,通过基本消息频道�来实现一些对性能较高的频道场景,例如埋点、网络请求等,通过方法频道来实现一些通用的本地方法调用,以及拓展业务特有逻辑的方法调用。
参数传递
在创建Ffltter页面时,借助Dart Entry Points Args�,可以从Native传递相应的参数,代码如下.
在Ffltter端,可以在入口点�中获取相应的参数。
// XXX主页
@pragma('vm:entry-point')
void XXX(List<String>? args) => SafeApp().run(ThemeApp(args: args, child: XXXPage(args)));
后续继续优化,可以将参数封装为一个地图,双端进行解析,这样在获取参数时能更加具有语义化。
桥接
Channels在这个方案中扮演着非常重要的角色,它是Ffltter和Native之间的纽带。我们根据频道的使用场景,将其分为了四类。
- NativeCommonApi:适用于与本地频繁通信或者对性能要求较高的场景。
- 报告异常:上报通用异常
- ReportTrackerImpression:上报页面曝光
- ReportTracker点击:上报点击
- ReportTrackerColumn:上报栏目曝光
- DoActionUrlCall:执行本机操作URL
- NativeFontApi:加载本地字体。
- LoadNativeFont:加载本地字体
- NativeNetApi:加载本地网络请求数据。
- GetNativeNetBridge:通用获取请求
- PostNativeNetBridge:通用POST请求
- 本地方法调用:适用于与本地的单次交互场景,通用的方法需要在这里新增,并在本地中新增实现。
- 完成:关闭Ffltter页面
- CanPopFlutterPage:是否可以Pop当前Ffltter页面(iOS用)
- IsInBookShelf:获取当前BookID是否在书架
- GetUserGender:获取当前用户性别
- ShowToast:原生显示吐司
对于性能要求较高的场景,我们使用基本消息频道�,而单次的本地调用,我们使用方法频道�,经过不同的场景(超大数据量、连续多次频繁请求)等测试,其数据符合预期,调用延时相对于请求时间来说,基本可以忽略不计,同时,其稳定性也经受住了考验。
在开发的早期阶段,桥接函数不太丰富的前提下,在开发Ffltter时,有时候还是需要Native开发人员对新的通用桥接函数进行补充,但随着函数的丰富,这个操作会越来越少,最后逐渐就不太需要Native开发人员参与Ffltter的开发与调试了。
UI组件化的实践
由于目前起点读书的轻量化引擎架构设计,Ffltter只作UI渲染,所以我们需要充分利用Ffltter的热更新特性,提高业务UI的开发效率。
黑夜模式与颜色令牌
目前起点读书的黑夜模式,有两种设置方式,一种是跟随系统,用户可以在应用内部设置,也可以在手机内进行切换,另一种是手动在应用内部设置固定黑夜模式或者非黑夜模式。
颤动页面在创建时,会传入当前应用程序设置黑夜模式的枚举-系统、轻、暗�,在颤动中,会根据设置的模式来进行切换。而如果用户在打开Ffltter页面后,在手机内进行黑夜模式的切换,Ffltter也会自动进行切换。相关代码如下.
在处理颜色的映射时,我们会根据设计给出的映射关系,根据是否为黑夜模式,将指定令牌映射为对应的色值,例如下面的示例。
Color get surface_gray_700 => isDarkMode ? white_alpha_70 : gray_700;
黑夜模式与非黑夜模式的设置是通过拓展Theme扩展�来实现的,并在材料App�中分别设置Theme、Dark Theme�和Theme�,从而利用Theme,在切换时,自动对颜色Token进行切换映射。
字体与文本样式
由于起点读书有内嵌字体,以及多行文本的字体矩阵问题,这些都会对设计师的文本设计造成困扰,在Ffltter中,我们通过结构样式�来与设计师对齐字体和字体矩阵的影响,让开发者在开发过程中,避免单独处理文本的设计问题,同时,也减轻设计师的走查工作量。
在代码中,只需要使用设计师给出的字体令牌即可,代码如下。
内嵌的本地字体,会在初始化的时候通过频道从本地桥接过来,借助字体加载器�来加载字体的uInt8列表�数据流。
UI组件库
统一UI组件库,可以让开发者在开发的过程中,快速创建符合设计规范的组件,减少开发工作量,同时也减少设计的走查工作量,目前直接运行Example中的Main.省道即可启动启动扑翼UI组件库展示程序,如下所示。
在这里开发者可以查看当前已有规范的UI组件,并查看相关示例代码,直接在项目中使用。同时,后续会抽取更多的通用组合组件,例如通用书卡、通用评论、工具栏等组件,进一步提高开发效率.
借助Ffltter的跨平台功能,Example可以非常方便的运行在WEB中,从而方便给设计师和产品进行走查。
图片外接纹理
Ffltter原生的图像处理方式存在一些内存问题,虽然使用简单,但是对内存水位的影响较大,特别是在复用一些本地缓存图片的场景,所以,针对图片的处理,我们使用了外接纹理的方式,借助纹理来实现图片在本地的处理逻辑,复用本地已有的、成熟的处理方式,例如在本地中使用中使用Glide进行图片加载,并控制缓存。
通过图片外接纹理,显著降低了Ffltter对于图片的内存消耗,同时也减少了内存抖动,让Ffltter更加稳定。相关技术方案,可以参考我的这篇文章.
颤动混编工程之打通纹理之路
埋点
对于业务应用程序来说,数据埋点,是一件非常重要的工作。起点读书目前在原生的埋点方案,存在很多准确性的问题,其原因就是原生的埋点方式是以数据作为驱动的,由于原生预加载的存在,就会导致有部分埋点提前进行了曝光,而在Ffltter中,埋点是以UI作为驱动的,所以其天生就更加符合产品的直观逻辑感受,所以相比原生,颤动的埋点会更加方便。
借助Ffltter开源的Visibility_Detector�(海外团队封装库Reportable),我们可以很方便的检测微件的渲染状态,从而对其进行埋点,封装后的代码如下。
埋点数据同样是通过频道桥接到原住民,复用原有的埋点和上报逻辑进行处理。
混编开发流程
当前起点Ffltter工程的目录结构如下。
其中:
- 是UI组件库的示例工程示例
- LIB/BIZ目录下,是业务开发的主要目录
当业务开发者拿到业务需求后,只需要在示例中增加业务页面的临时入口,即可进入开发流程。
通常情况下,我们会先进行需求评审,接下创建接口协议,并输出接口Mock数据,在Ffltter业务的开发过程中,需要首先在Example中,增加Mock数据,如下图所示.
然后在QDFlutterDemoMainPage�中,增加模拟的支持。
这样处理之后,我们在开发Ffltter业务逻辑时,就可以直接运行Ffltter代码,而不用依赖原生。最后,在lib/main.dart中,增加业务逻辑页面的入口函数。
如果业务不包含特殊的业务处理,则直接通过�基本流畅活动。启动�的方式进行调用即可,如果是包含特殊业务处理的,则需要使用其继承类来进行调用,并在继承类中,实现自身的特殊业务处理。
在当前Git业务分支开发完成后,需要在当前Git分支执行Build_aar.sh脚本,编译aar包到指定的Native目录下,然后在Native正常进行编译即可,在混编模式下,Ffltter页面会自动适配到从Native获取数据,而不是从Mock端获取数据,此时即可与后端进行联调。
在调试编译下,可以通过颤动附加来进行断点调试。
当功能测试完成后,需要将业务分支合并到MASTER分支,并重新编译aar后,合入本地的MASTER分支,并进行回归测试。
收益
在使用Ffltter对Native业务进行辅助开发后,带来的收益主要是下面几个方面。
首先,对于开发人员来说:
- 提升本地业务开发效率,原本双端的开发工作,可以统一为单端开发,效率提升将近一倍
- 双端业务逻辑能保持统一,避免出现iOS、安卓不一致的场景
- 提升编译速度,借助Ffltter的热重载和本地模拟机制,可以提高30%的开发效率,不用再等待漫长的编译
其次,对于测试人员来说:
- 测试人员可以针对单端设备进行业务逻辑的重点测试,再对双端进行回归验证,可以避免在双端执行重复的测试用例
- 对于埋点的测试,更是可以减少一半的重复验证工作
另外,对于设计人员来说:
- 设计师可在进行视觉验收时,可以以单端为主,另一端为辅的方式进行走查,验收效率提升将近一倍
- 由于双端设计统一,不用再处理某端阴影、字体、模糊等需要单独适配的场景,也提高了设计的统一度
业务实践
在起点读书最新上线的新版书单广场页面中,我们使用Ffltter来进行开发,打通了Ffltter和Native之间的从评审、开发、测试到视觉走查的一系列流程。
欢迎大家体验.
欢迎大家关注我的公众号--[群英传],专注于《安卓》《扑扑》《科特林》
我的语雀知识库--www.yuque.com/旭易胜
相关推荐
- 如何在WordPress中创建客户端仪表板
- 一个优雅解决多个弹窗顺序显示方案
- 火热报名中 | 抖音客户端基础技术大揭秘
- 鸿蒙HarmonyOS:Web组件初体验与离线包方案探索
- 不当暖宝宝,Android 耗电检测之路
- 如何在WordPress中创建客户端门户
- 如何防止客户端停用WordPress插件
- 二本2年跳槽大厂 |新的篇章,新的起点
- 我们将快速了解Yahoo SMTP服务器的详细信息,以及它的POP3和IMAP设置。然后我们将向您展示如何将您的电子邮件客户端连接到Yahoo SMTP服务器。
- 我们将首先快速共享Microsoft 365 SMTP设置以及POP3和IMAP设置(允许您接收电子邮件,而SMTP用于发送电子邮件)。然后,我们还将向您展示如何配置您的WordPress网站以使用Microsoft 365发送电子邮件。
- 程序开发学习排行
- 最近发表
-
- Dropchat最好的wordpress常用插件下载博客插件模块
- 由SPUR最好的WordPress常用插件下载博客插件模块提供的单片眼镜
- ALGO站点加载器最好的WordPress常用插件下载博客插件模块
- Marin WordPress主题博客主题下载
- 旅游度假WordPress主题博客主题下载
- Kenta Writer Hub WordPress主题博客主题下载
- WII DLC+WiiWare+VC全集目录!下载索引
- WII中文游戏全集目录!下载索引
- Healthy Fitness健身房WordPress主题博客主题下载
- Classic Industry WordPress主题博客主题下载