Flutter开发之《闲鱼的探索与收获》笔记(51)

本篇内容是根据闲鱼的匠修,本名叫熊华丽的做的演讲内容做的笔记。本文的内容只是认为自己需要学习的地方。
演讲实录——Flutter-闲鱼的探索与收获

Flutter基本知识

在这里插入图片描述
(PPT图示)左边是Flutter大概的架构图,它分为两层,一个是底下的C++实现的Engine层面运行与检索,还有上面用Dart实现的Framework。Flutter就是通过这两层,它仅仅借用平台原生的图形渲染能力,使用定制的运行引擎和UI Widget,在底层实现跨端。这种做法的技术成本是很高的,有可能只有像谷歌这样的爸爸才能做得出来。因为它采用这种做法,它有自定义的Engine和Framework,所以它在在技术上可以做到非常深度的优化,所以它的运行性能就非常好。

首先,Native拥有最好的用户体验,开发成本也最高。H5大幅降低了开发成本,d但也牺牲了用户体验。RN就是在H5的输入上,对用户体验做了优化,但我们觉得它依然不是很完善,因为RN最近发展得不是很顺利。Flutter有比较好的开发效率,几乎可以媲美Native的运行性能,它的用户体验非常好。非常适合用来对开发效率对跨端有要求,同时又要保持有良好用户体验的场景。在闲鱼里,我们通常使用Flutter来开发我们的主流业务。

闲鱼是一个非常大的APP,不仅有Flutter,也有Native开发,也有H5的开发,还引入了集团Widget开发。就是说,我们有4套技术栈。我们的想法非常简单,就是在具体的业务场景下选择最合适的技术栈,充分利用这些技术栈各自的优势做到取长补短,相互补充。

混合栈

在这里插入图片描述
现在闲鱼的首页有这样的场景,有4个Tab,下面有个Tab是社区。我们引入Flutter后就想能不能把它改成Flutter开发,然后改善客户体验。我们研究了一下发现,Flutter提供的能力,现在是把它放在Flutter里面打包给你,要不你就不用。它是不能做到混合的,比如部分使用Flutter,另外一部分还保持原生,Flutter现在还没有这个能力。

Flutter的页面和普通的页面会交叠出现,它会对接很多的页面栈,这对内存的使用是一个很大的压力。其实这不光光对内存使用是很大的压力,它限制了很多优化的场景。比如一个Flutter页面,如果它被另外一个Flutter页面盖住的时候,这个Flutter页面对用户来说是不可见的,我们可以把被盖住的页面里面很多资源释放掉,正在加载的资源也可以把它做一个暂停,因为它也不可见了。但是如果每一个Flutter页面都是放在各自的环境里面,它在自己的环境里都是属于最上层的页面,那我们就没办法去做这样的优化了。

基于此,闲鱼建设了一个混合栈。将Flutter引入到整个工程中来,最起码还要分为两批页面,一批是Flutter页面,一批是native页面。要实现这两个页面之间协调调动,实现混合使用,实现业务功能的话,中间一定要有一个调动的逻辑层,整个混合栈就是一个混合调动的逻辑层。

在这里插入图片描述

混合栈提供三个能力:

第一,最基础的能力,要把Flutter页面无差别接入到本地页面的路由系统里,本地的其他页面就可以很好地通过本地路由系统去打开Flutter页面,它就可以很好的在业务实现上做很好的协同。

第二,需要补充Flutter嵌入的开发能力。谷歌已经意识到这个问题,也往这方面做优化。我们在建设的这个东西也一直在跟进,如果谷歌放出这方面的能力,我们后面可能会把谷歌的能力很快补充进来。

第三,你要统一调度这两种页面栈的话,它是一个复杂的逻辑,整个混合栈需要对这些逻辑进行分装,要对Flutter和Native交叠出现的场景做必要的优化,整个产品才能达到上线的标准。

混合栈在闲鱼里已经做了两个版本的迭代。经过第一个版本的实践之后发现,如果要协同调度好两个页面栈,并不是一件非常容易的事情。在安卓里面各个页面栈是一件非常复杂的事情,在安卓里一个APP可以起多个页面连接栈,在栈中每次打开的时候都有4种打开模式,它的行为是非常复杂的,因为我们还要支持后面Flutter的页面模式,所以它整个逻辑是非常复杂的。在后期开发的时候,为了简化这种逻辑,我们在做Flutter部署的时候要确定一些原则,所有的Flutter环境中的页面栈行为,都必须通过本地去驱动它。也就是说,要通过Native里面的生命周期去驱动容器里Flutter页面的生命周期。打个比方,比如说我现在有个Flutter页面在跟用户交互,当用户点击back键的时候,Flutter页面理论上马上就要pop,如果用混合栈的话,它不能自己去调度,必须把这个团传递到混合栈里面去,混合栈会再去驱动里面的Flutter页面,通过这样一种逻辑,有这样的原则的话,后面做很多功能开发,做能力拓展的时候,就不至于把这个逻辑搞得特别复杂,因为搞复杂之后你可能自己都理不清楚它们之间双向的驱动关系。这样做的前提是此,要实现Activity和Flutter中的页面,要实现在逻辑上的一一映射。

经过一段时间的实践之后,在做Flutter部署里面,总结出Flutter混合栈实现的几个要点。

第一,这是一个小坑,我们要实现Flutter页面的生命周期和Native的生命周期做很好的互通和兼容,它很容易产生坑。打开一个新的Activity,我们通常会走Opors(音),然后再走一下Ostop(音)。但是在有些情况下,比如设置了特殊的主题或者有些特殊的场景下,它可能仅仅会走一个Opors生命周期,它不会走到Ostop里面,在实现的时候对这种场景要有充分的考虑。

第二,因为Flutter现在还不能很好地深度使用,我们要把Flutter的一些环境从Flutter Activity中剥离出来,然后做一个标准运行容器的定义,要做一个基础的分装给到开发者,这样开发者才能非常灵活去是否Flutter的能力,他可以把Flutter当作Activity的一部分去嵌入使用。

第三,我们要实现前面讲的原则,就是说,所有Flutter层的页面栈行为都要用Native层去驱动,这有一个前提,所有Flutter页面和本地容器的Activity都有一个逻辑上的映射关系,但整个安卓APP的栈管理非常复杂,它的数据结构非常复杂,它可能不是一个单纯的栈的数据结构,因为每个APP运行的时候可以起多个test的栈,每个Activity的行为都很复杂,因为它有4种启动模式,它不是一个简单的行为,你打开Activity的时候有可能这个Activity会新起一个页面栈,有可能这个Activity会复用老的页面栈的实例,它有可能会在前面的栈里面找到这个Activity,然后把上面这些Activity全部出栈,整个行为很抽象也很复杂。Flutter是对这种行为的特别延展,它的抽象很简单,就是一个简单的栈,它的行为也可以简单获取。

我们研究了一段时间的Flutter代码之后,发现Flutter默认有个栈管理的能力,简单的页面栈行为管理的能力,但是它又允许你自己实现页面栈管理的能力,我们在Flutter实现了我们想要的页面栈管理的能力,通过这样来实现逻辑上的一一映射关系。

在这里插入图片描述

fish-redux

在这里插入图片描述

基于这四个需求,闲鱼在后期开发了自己的业务模型框架,就是fish-redux。这是社区标准的Redux概念,如果大家熟悉Redux的话不用担心,就是你们熟悉的原汁原味的Redux,我们没有做破坏。它提供一个Component层,就是一个组件。还有一个Adapter层,这是一种高阶的进阶
在这里插入图片描述
Component是我们设计的核心,我们对Component的定义,它是一个最小的业务单元,有自己的数据、逻辑,在某种情况下是一个自闭单元。Stateful是一个常用的组合,在安卓里面可以用。

你可以通过d在交互的时候发出一个action的数据。也可以通过S去监听,提供页面数据的连接器,从页面的数据里把自己要的数据取到。整个组件里是有逻辑的,需要改变数据的同步的逻辑,把它放在Redux里面。

最后还有一个非常重要的是Slods,是组件插槽。通常有些组件并不关心具体的业务实践,相当于定义接口,类似于细节类的方式,把具体要实现的功能点通过插件的方式流出去,自己去关注怎么组合起来,通过叫做模版组件。

我们大概看一个例子,就是闲鱼的宝贝详情页。首先看这个页面,最大的就是Component,外层的Component不关注具体的业务,会根据不同的数据去组合出不同的宝贝详情页来,具体的功能流给下一层的Component实现,比如有视频的Component,有留言等。通过这种方式就可以很好地实现分治和复用。我们在开发新页面的时候,通常可以用到老页面里面的很多元素,我们只需要对某些特定的Component去实现就够了,可以利用老的Component,通过新的Component来组合它,加速开发。

flutter_boost:
https://github.com/alibaba/flutter_boost

fish_redux:
https://github.com/alibaba/fish-redux

发布了249 篇原创文章 · 获赞 224 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/shifang07/article/details/98614618