联系我们
简单又实用的WordPress网站制作教学
当前位置:网站首页 > 程序开发学习 > 正文

颤动混编方案在起点客户端的实践之路

作者:访客发布时间:2023-12-13分类:程序开发学习浏览:79


导读:起点读书客户端一直紧跟新技术的潮流,从很早开始,就在进行Ffltter的尝试,在筹备了许久之后(移除了包大小的Kpi指标),我们终于在最新的业务开发中,使用了Fflighter。颤...

起点读书客户端一直紧跟新技术的潮流,从很早开始,就在进行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/旭易胜


标签:之路客户端起点方案颤振


程序开发学习排行
最近发表
网站分类
标签列表