41 聊聊Flutter,面对层出不穷的新技术该如何跟进? “天下苦秦久矣”,不管是H5、React Native,还是过去两年火热的小程序,这些跨平台方案在性能和稳定性上总让我们诟病不已。最明显的例子是React Native已经发布几年了,却一直还处在Beta阶段。

Flutter作为今年最火热的移动开发新技术,从我们首次看到Beta测试版,到2018年12月的1.0正式版,总共才经过了9个多月。Flutter在保持原生性能的前提下实现了跨平台开发,而且更是成为Google下一代操作系统Fuchsia的UI框架,为移动技术的未来发展提供了非常大的想象空间。

高性能、跨平台,而且更是作为Google下一个操作系统的重要部分,Flutter已经有这么多光环加身,那我们是否应该立刻投身这个浪潮之中呢?新的技术、新的框架每一年都在不断涌现,我们又应该如何跟进呢?

Flutter的前世今生

大部分所谓的“新技术”最终都会被遗忘在历史的长河中,面对新技术,我们首先需要持怀疑态度,在决定是否跟进之前,你需要了解它的方方面面。下面我们就一起来看看Flutter的前世今生。

Flutter的早期开发者Eric Seidel曾经参加过一个访谈What is Flutter,在这个访谈中他谈到了当初为什么开发Flutter,以及Flutter的一些设计原则和方向。- -

Eric Seidel和Flutter早期的几位开发人员都是来自Chrome团队,他们在排版和渲染方面具有非常丰富的经验。那为什么要去开发Flutter?一直以来他们都为浏览器的性能而感到沮丧,有一天他们决定跳出Web的范畴,在Chromium基础上通过删除大量的代码,抛弃Web的兼容性,竟然发现性能是之前的20倍。对此我也深有感触,最近半年也一直在做主App的Lite版本,安装包也从42MB降到8MB,通过删除大量的历史业务,性能比主包要好太多太多。

正如访谈中所说,Flutter是一个Google内部孵化多年的产品,从它开发之初到现在,一直秉承着两个最重要的设计原则:

  • 性能至上。内置布局和渲染引擎,使用Skia通过GPU做光栅化。选择Dart语言作为开发语言,在发布正式版本时使用AOT编译,不再需要通过解析器解释执行或者JIT。并且支持Tree Shaking无用代码删除,减少发布包的体积。
  • 效率至上。在开发阶段支持代码的Hot Reload,实现秒级编译更新。重视开发工具链,从开发、调试、测试、性能分析都有完善的工具。内置Runtime实现真正的跨平台,一套代码可以同时生成Android/iOS应用,降低开发成本。

那为什么要选择Dart语言?“Dart团队办公室离Flutter团队最近”肯定是其中的一个原因,但是Dart也为Flutter追求性能和效率的道路提供了大量的帮助,比如AOT编译、Tree Shaking、Hot Reload、多生代无锁垃圾回收等。正因为这些特性,Flutter在筛选了多种语言后,最终选择了Dart。这里也推荐你阅读Why Flutter Uses Dart这篇文章。

总的来说,Flutter内置了布局和渲染引擎,使用Dart作为开发语言,采用React方式编写UI,支持一套代码在多端运行的框架。但是正如专栏前面所说的,大前端时代的核心诉求是跨平台和动态化,下面我们就一起来看看Flutter在这两方面的表现。

1. Flutter的跨平台开发

虽然React Native/Weex使用了系统原生UI组件,通过原生渲染的方式来提升渲染速度和UI流畅度,但是因为JS执行效率、JSBridge的通信代价等因素,性能依然存在瓶颈,而且我们也无法抹平不同系统的平台差异,因此这样的跨平台方案注定艰难。

正如Eric Seidel在访谈所说,Flutter是从浏览器引擎简化而来,无论是它的布局引擎(例如也是使用CSS Flexbox布局),还是渲染流水线的设计,都跟浏览器都有很多相似之处。但是它抛弃了浏览器沉重的历史包袱和Web的兼容性,实现了在保持性能的前提下的跨平台开发。

回想一下在专栏第37期《工作三年半,移动开发转型手游开发》中,我们还描述过另外一套内置Runtime的跨平台方案:Cocos引擎

在我看来,Cocos和Unity这些游戏引擎才是最早并且成熟的跨平台框架,它们对性能的要求也更加苛刻。即使是“王者荣耀”和“吃鸡”这么复杂的游戏,我们也可以做得非常流畅。

Flutter和游戏引擎一样,也提供了一套自绘界面的UI Toolkit。游戏引擎虽然能实现跨平台开发,但它致力于服务更有“钱途”的游戏开发。游戏引擎对于App开发,特别是混合开发支持并不完善。

如下图所示,我们可以看到三种跨平台方案的对比,Flutter可以说是三者中最为轻量的。

2. Flutter的动态化实践

在专栏第40期《动态化实践,如何选择适合自己的方案》中,我提到了一个观点:“相比跨平台能力,国内对大前端的动态化能力更加偏执”。

在性能、跨平台、动态性这个“铁三角”中,我们不能同时将三个都做到最优。如果Flutter在性能、跨平台和动态性都比浏览器更好,那就不会出现Flutter这个框架了,而是成为Chromium的一个跨时代版本。

浏览器选择的是跨平台和动态性,而Flutter选择的就是性能和跨平台。Flutter正是牺牲了Web的动态性,使用Dart语言的AOT编译,使用只有5MB的轻量级引擎,才能实现浏览器做不到的高性能。Flutter的第一波受众是Android上使用Java、Kotlin,iOS上使用Objective-C、Swift的Native开发。未来Flutter是否能以此为突破口,进一步蚕食Web领域的份额,现在还不得而知。

那Flutter是否支持动态更新呢?由于编译成AOT代码,在iOS是绝对不可以动态更新的。对于Android,Flutter的动态更新能力其实Tinker就已经实现了。从官方的提供方案来看,其实也只是替换下面的变化文件,可以说是Tinker的简化版。

官方的动态修复方案可以说是非常鸡肋的,并且也是要求应用重启才能生效。如果同时修改了Native代码,这也是不支持的。

更进一步说,Flutter在Google Play上是否允许动态更新也是抱有疑问的。从Google Play上面的开发者政策中心规定上看,在Google Play也是不允许动态更新可执行文件。

《从Flutter的编译模式》一文中,我们可以通过

flutter build apk –build-shared-library 将Dart代码编译成app.so。无论是libflutter.so,还是app.so(其实

vm_/* 、

isolate_/* 也是可执行文件)的动态更新,都违反了Google Play的政策。

当然不排除Google为了推广Flutter,为它的动态更新开绿灯。最近我也在咨询Google Play的政策组,目前还没有收到答复,如果后续有进一步的结果,我也可以同步给各位同学。

总的来说,Flutter的动态化能力理论上只能通过JIT编译模式解决,但是这会带来性能和代码体积的巨大影响。当然,闲鱼也在探索一套Flutter的布局动态化方案,你可以参考文章《Flutter动态化的方案对比及最佳实现》

面对新技术,该如何选择

通过上面的学习,我们总算对Flutter的方方面面都有所了解。可以说Flutter是一个性能和效率至上,但是动态化能力非常有限的框架。

目前闲鱼App美团外卖今日头条App爱奇艺开播助手网易新闻客户端、京东JDFlutter马蜂窝旅游App,都分享过他们在使用Flutter的一些心得体会。如果有兴趣接入Flutter,非常推荐你认真看看前人的经验和教训。

无论是Flutter,还是其他新的技术,在抉择是否跟进的时候,我们需要考虑以下一些因素:

  • 收益。接入新的技术或者框架,给我们带来什么收益,例如稳定性、性能、效率、安全性等方面的提升。
  • 迁移成本。如果想得到新技术带来的收益,需要我们付出什么代价,例如新技术的学习成本、原来架构的改造成本等。
  • 成熟度。简单来说,就是这个新技术是否靠谱。跟选择开源项目一样,团队规模、能力是否达标、对项目是否重视都是我们需要考虑的因素。
  • 社区氛围。主要是看跟进这个技术的人够不够多、文档资料是否丰富、遇到问题能否得到帮助等。

1. 对于Flutter,我是怎么看的

Flutter是一个非常有前景的技术,这一点是毋庸置疑的。我曾经专门做过一次全面的评估分析,但是得出的结论是暂时不会在我负责的应用中接入,主要原因如下。

目前我还没有跟进Flutter的核心原因在于收益不够巨大,如果有足够大的收益,其他几个因素都不是问题。而我负责的应用目前使用H5、小程序作为跨平台和动态化方案,通过极致优化后性能基本可以符合要求。

从另外一方面来说,新技术的学习和引入,无论是对历史代码、架构,还是我们个人的知识体系,都是一次非常好的重构机会。我非常希望每过一段时间,可以引入一些新的东西,打破大家对现有架构的不满。

新的技术或多或少有很多不完善的地方,这是挑战,也是机会。通过克服一个又一个的困难和挑战,并且在过程中不断地总结和沉淀,我们最终可能还收获了团队成员技术和其他能力的成长。以闲鱼为例,他们在Flutter落地的同时,不仅将他们的经验总结成几十篇非常高质量的文章,而且也参加了QCon、GMTC等一些技术大会,同时开源了fish-reduxFlutterBoost等几个开源库,Flutter也一下成为了闲鱼的技术品牌。

可以相信,在过去一年,闲鱼团队在共同攻坚Flutter一个又一个难题的过程中,无论是团队的士气还是团队技术和非技术上的能力,都会有非常大的进步。

2. 对于Flutter,大家又是怎么看的

由于我还并没有在实际项目中使用Flutter,所以在写今天的文章之前,我也请教了很多有实际应用经验的朋友,下面我们一起来看看他们对Flutter又是怎么看的。

总结

曾几何时,我们一直对Chromium庞大的代码无从入手。而Flutter是一个完整而且比WebKit简单很多的引擎,它内部涉及从CPU到GPU,从上层到硬件的一系列知识,源码中有非常多值得我们挖掘去学习和研究的地方。

未来Flutter应用在小程序中也是一个非常有趣的课题,我们可以直接使用或者参考Flutter实现一个小程序渲染引擎。这样还可以带来另外一个好处,一个功能(例如微信的“附近的餐厅”)在不成熟的时候可以先以小程序的方式尝试,等到这个功能稳定之后,我们又可以无成本地转化为应用内的代码。

Dart语言从2011年启动以来,一直想以高性能为卖点,试图取代JavaScript,但是长期以来在Google外部使用得并不多。那在Flutter这个契机下,它未来是否可以实现弯道超车呢?这件事给我最大的感触是,机会可能随时会出现,但是需要我们时刻准备好。

“打铁还需自身硬”,我们还是要坚持修炼内功。对于是否要学习Flutter,我的答案是“多说无益,实践至上”。

课后作业

对于Flutter,你有什么看法?你是否准备在你的应用中跟进?欢迎留言跟我和其他同学一起讨论。

Flutter作为今年最为火热的技术,里面有非常多的机遇,可以帮我们打造自己的技术品牌(例如撰写文章、参加技术会议、开源你的项目等)。对于Flutter的学习,你可以参考下面的一些资料。

欢迎你点击“请朋友读”,把今天的内容分享给好友,邀请他一起学习。我也为认真思考、积极分享的同学准备了丰厚的“学习加油礼包”,期待与你一起切磋进步哦。

参考资料

https://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/Android%e5%bc%80%e5%8f%91%e9%ab%98%e6%89%8b%e8%af%be/41%20%e8%81%8a%e8%81%8aFlutter%ef%bc%8c%e9%9d%a2%e5%af%b9%e5%b1%82%e5%87%ba%e4%b8%8d%e7%a9%b7%e7%9a%84%e6%96%b0%e6%8a%80%e6%9c%af%e8%af%a5%e5%a6%82%e4%bd%95%e8%b7%9f%e8%bf%9b%ef%bc%9f.md