闲鱼研发框架应用和探索

一、闲鱼Flutter研发框架使用现状

闲鱼是一个侧重于电商业务的平台,因此随着业务的不断增长,系统的逻辑复杂度也在不断提升。因为属于电商业务,所以对于流量和运营的数据具有较高的需要,因此在闲鱼的体系中也需要具备动态性的能力,并且还需要通过增加特效的能力来增加用户的感知,丰富用户的体验。

屏幕快照 2020-06-22 下午2.06.02.png

二、Flutter研发框架下一代模式

一体化模式

下图中左侧是传统的客户端-服务器架构。在这样的CS架构下,对于客户端开发者而言,往往都会经历相似的痛点。当产品的需求过来,可能客户端的开发同学并不能自己完成,而需要牵扯到服务端的开发,可能需要对于协议进行补充或者添加更多的接口能力。而对于后端开发同学而言,面对一个需求也可能需要领域服务的支持。这样一来,一个貌似很简单的需求,却需要从客户端到后端再到领域服务的相互协调,进而会影响需求的排期问题。而如果客户端也可以写服务端的代码,这样的问题是否就能够被解决掉呢?

屏幕快照 2020-06-22 下午2.06.50.png

在目前闲鱼所给予的FaaS框架下的一些场景中也存在上述痛点。如下图所示的是传统基于FaaS的模式,可以看出使用FaaS能够将逻辑和UI彻底进行分离,但是在端上的逻辑部分,无外乎两种,一种是数据的拉去和推送,另外一种是数据的主账号。在后端也会有类似的逻辑,只不过此时不是客户端找服务端要数据,而是服务端找各个领域层要所需要的数据,然后进行数据的加工,再将数据以面向客户端协议的部分进行主账号推送。而上述两个部分存在着一定的逻辑割裂,并且也存在一定的重复工作,因为数据转化被执行了两次。那么,是否能够将上述两种逻辑合二为一,并且让端上的同学进行开发,同时将逻辑后端化呢?结合如今Serverless的能力,可以做到在轻量级能力下支持多语言的开发。

屏幕快照 2020-06-22 下午2.07.21.png

基于上述的背景,闲鱼在今年实现了一体化的研发解决方案。在云侧兼容了集团通用的Gaia容器化能力,用Dart语言实现了容器化的部分。之所以使用Dart是因为这部分与Flutter对应。阿里巴巴希望客户端写后端的情况与Flutter使用一体化的语言来完成,屏蔽两者之间的差异。在端侧研发了Nexus一体化插件,将现在面向Action的部分可以实现端侧与云侧的一体化。这样的好处在于在端侧叫Action,在云侧也叫Action,而在端上进行开发的时候并没有感知云侧Action的存在,这就是Nexus的核心作用。此外,现在面向于通信协议其实就是面向于API接口的一部分,这样能够实现端上的高性能和逻辑内聚。

屏幕快照 2020-06-22 下午2.07.40.png

这里简单介绍一下一体化框架的具体落地场景。对于下图所示的闲鱼下单的页面而言,在原有模式下可能需要5个请求接口,这部分请求接口可能部分在端上,部分在云上,并且通过一条信息流进行合并。这种情况下如果需要修改某种状态就会非常复杂。在改造完成之后就将原来的5个请求接口全部实现Action协议化,这样的好处在于云端的模型统一了,无论是对于云还是客户端都在写同样的逻辑,只不过这样的逻辑部署到了云上。其次,还屏蔽掉了协议的具体部分,只留下了协议名称。第三点好处在于实现了逻辑的归一,所有的逻辑都实现了云端化,大家在书写这样的逻辑时不会存在割裂,最终书写的逻辑都是面向云模型的状态。第四个优点是冗余代码将会大大减少。而最大的好处在于形成了很好的业务的闭环,让客户端开发也可以应用开发的部分工作。

屏幕快照 2020-06-22 下午2.08.13.png

三、Flutter研发框架下动态能力

闲鱼本质上主要是一个电商业务平台,其在于流量侧具有强运营时效的特性,很多的运营活动或者决策需要得到及时的响应,如果在这种情况下不具有动态性就会陷入被动。完整的动态性包括了逻辑动态性和UI动态性,但是在流量侧部分更加注重UI动态性,轻逻辑重UI。接下来将与大家分享在Flutter侧如何使用这样一个微能力的解决方案。

屏幕快照 2020-06-22 下午2.08.41.png

动态模板

动态模板在阿里巴巴整个集团内部都是一套比较成熟的解决方案。首先,通过DX平台编辑模板,编辑成二进制文件并生成模板下载链接,之后模板下载解压,进行表达式或者事件的注册,并对于数据进行绑定解析,使得组件得到渲染。借助于集团动态模板的成熟方案,所需要解决的就是在Flutter侧如何满足DSL的UI表达,来实现UI布局。

屏幕快照 2020-06-22 下午2.09.12.png

核心问题-Layout

熟悉安卓或者Flutter的人会发现这两部分的UI表达其实是格格不入的,那么如何在Flutter侧实现一套安卓UI布局呢?其实完整的UI表达是样式+布局+内容组合实现的。根据Flutter的源码可以看出,在其布局表达里面,样式、布局、内容三个要素表达是彻底分离的。相反而言,在安卓的DSL的架构里面,样式和布局是结合的,内容部分是分离的。如果将安卓的部分也进行拆分可以一一映射到Flutter中,虽然描述部分可以很容易地做映射,但是核心困难在于布局部分,主要是关于大小的抽象性描述,因此需要了解在Flutter侧是如何表达布局的约束的。

屏幕快照 2020-06-22 下午2.09.34.png

其实在Flutter侧主要有两种对于布局的约束设计,分别是盒子模型和条子模型,而以上两种都是感性描述的约束性布局。除此之外,还提供了30多个布局的容器部分。这是因为基于上面的感性描述的约束布局情况下,Flutter可能会存在大量的冗余代码,在约束布局情况下就会显得特别复杂。另外一部分在于性能部分,感性描述远远没有大于量行描述,因此Flutter提供的30多个量行约束是对于性能的考究。反观安卓的布局部分,相对比较少,大约为4、5个,所以这里的问题就是如何将安卓的布局部分使用Flutter的布局来表达或者描述。如果想要使用特性来做映射是很困难的,如果退而求其次,使用共性部分的盒子模型和条子模型似乎可以表达。

布局表达

如果在端侧已经完成对于动态模板树形结构的解析之后,就能够很容易地将树形结构的节点实现如下图所示的一拆三结构。第一层是装饰层结构,中间层可以基于自低向上和自顶向下的计算规则重新计算出大小,最后一部分则是将内容想要表达的叶子界面进行Backup。为了实现安卓这样的布局结构阿里巴巴引入了安卓的Spec Model模型,其很主要的作用就是表达当需要做依赖于内容适配等情况下,可以使用Min_width的最大估算来预估大小部分,再从自底向上来计算出实际的Size。动态模板在Flutter侧的实现主要解决的就是这样的侧重点部分。

屏幕快照 2020-06-22 下午2.09.55.png

业务效果

整套方案经过闲鱼一整年的打磨之后,已经有大量的业务上线和应用了。无论是卡片还是其他布局部分,都能够使用Flutter UI实现。

屏幕快照 2020-06-22 下午2.10.28.png

性能参考

动态性部分往往会和性能存在一定的博弈。在闲鱼的实践中得到的实际结果表明,使用动态模板的DSL来表达的性能还可以接受,线上的实际效果大约在55帧左右,相比于正常使用Flutter原生的60帧仅仅存在可被接受的一点差距。

屏幕快照 2020-06-22 下午2.10.49.png

性能的下一步探索

虽然目前的方案和Flutter原生仅存在5帧的差距,但是如果能够进一步优化,还是有可能达到原生的性能要求的。下图中分别展现了使用Flutter原生和DX写的卡片布局,可以直观地发现在Flutter原生使用了大量的高阶型特性表达,在DX中则基本都是常见的容器布局,并且树形结构的深度层次远远大于Flutter原生。DX中使得长度变大的部分在于装饰性的布局部分,因此可以尝试地探索在DSL的表达部分将Padding在容器层进一步缩短结构,可能会提高FPS,也就是将现在的简单容器布局进行特性升级。

屏幕快照 2020-06-22 下午2.11.15.png

四、Flutter研发框架下互动能力

背景与现状

在电商领域的业务里面,很多业务想要通过游戏化的方式创造更有表现力的交互体验,创造新的业务玩法和价值。传统的UI表达方式,越往后就会越受限,因此需要将UI和游戏引擎的边界打破,让UI具有游戏的丰富动效能力,也让游戏引擎具有UI的丰富控件能力。在传统APP的框架下,所能够做的无外乎嫁接游戏引擎,而这样的游戏引擎和原来的APP是格格不入,也是不相通的,其能够带来的最大效果就是开辟一个独立的页面来承载游戏,但这样的方式似乎不是所想要达到的设计理念。在Flutter侧,今年推出了Flame这个游戏框架,其解决了单边引用的过程。Flame使得在Flutter框架里面可以将游戏的控件进行合拢,但是无法实现在游戏里面合拢UI界面,因此提供了单边能力。Flame虽然没有完全解决双边打通的诉求,但是还是提供了很好的思路。

屏幕快照 2020-06-22 下午2.11.38.png

核心问题-融合

目前而言,所需要解决的核心问题就是将UI和游戏引擎融合。Flame的表现形式其实就是将完整的游戏封装在起来,能够很好地将游戏插入到UI中。假如将Flame游戏引擎的表达也用类似于RenderObject树形结构的表达,就会形成两棵Flutter体系下的树结构,能够很好地进行融合比对。闲鱼在这样的思路下进行了新的探索和尝试,重新设计了一套互动游戏引擎,弥补了Flame不能满足的需求问题。

屏幕快照 2020-06-22 下午2.12.04.png

Candy整体设计

Candy是符合ECS标准的,与Flutter高度融合的原生开发高性能互动开发框架。Candy在架构设计上完全按照ECS的标准;在接口设计上对齐了阿里巴巴集团的互动EVA,使得集团内部在使用时不会对于接口感到陌生;在应用能力上,Candy完全融入了Flutter的绘制体系;在扩展能力上,Candy保留了游戏子系统化能力的补充,能够满足UED主流能力,使得不同公司或者行业开发者能够更好地使用自己所熟悉的工具体系。

屏幕快照 2020-06-22 下午2.12.25.png

效果

在闲鱼中,签到、换取闲鱼币等常用的按钮在游戏中使用了Flutter的游戏控件,能够非常简单地将游戏以Widget形式插入到Flutter页面中,而这对于使用者而言不会产生任何感知。此外,对于传统应用的开发者,也能够很轻松地将具有动画能力、游戏能力的控件外透,并且与UI进行融合。

屏幕快照 2020-06-22 下午2.12.46.png

效果-骨骼

展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java