曾经的团队是国内最早投入Flutter框架怀抱的团队,后来又有机会负责起了Flutter相关项目,翻回以前写的文章,感慨良多,这是其中的一篇关于这些内容的闲聊。
| 导语Flutter相关的技术资源官网和网友都有过系统且细致的整理,因此这篇文章不是系统的介绍Flutter,而是把我的学习Flutter的一些感受记录分享,内容组织比较零散,想到哪说到哪,欢迎留言讨论。
Dart是Flutter的编程语言,Flutter是Google的UI工具包,用于从单个代码库构建漂亮的本机编译的移动,Web和桌面应用程序。
接下来我们从Dart到Flutter,再到Flutter engine,聊一下我印象深刻的点。
我一直在项目中反对组员直接使用_beginthread的多线程并发,因为很多人不考虑函数的可重入性,导致埋下许多坑,在我看来多线程弊大于利,于是严格要求大家只能用PostToXxThread的方式使用多线程。而我发现Dart对多线程并发的设计正是我所需要的,彻底解决了多线程加锁互斥的难题,相当于强制使用Post方式,即满足了并发的要求也解决了多线程最让人头疼的线程同步,真是填补了个大坑,Dart干得漂亮!
单线程如何解决IO等耗时操作导致的无响应呢?推荐的做法是async-await方式,总体上Dart的async-await设计和JavaScript以及C#的设计大同小异,使用体验好。async-await的方式到了底层其实就是多线程(也不排除协程),但是如果想要像dart的这种async-await编写体验则必须让语言支持垃圾回收,因为在不支持垃圾回收的语言(如C++)是无法处理后await返回后栈对象或者this被释放的场景,因此类似C++语言目前只有“鸡肋版的async-await”。Dart runtime的线程模型基本和chromium高度一致。
我们通过C++实现了win/mac的跨平台,但是代码里大量的空指针保护代码让我很难受,有时有人忘写了指针判断导致崩溃也会让人很头疼,而Dart也很好的解决了这个问题:
这篇文章对Dart的空安全讨论非常深入:深入理解空安全 | Dart
在其中看到这段话也非常认同:“代码的健全性极大程度地决定了开发者对于自己的代码是否有自信。一艘 大部分时间 都在飘忽不定的小船,是不足以让你鼓起勇气,驶往公海进行冒险的”。
避空运算符是个非常好用的语法糖,但是也会导致很多逻辑缺失异常处理,降低代码鲁棒性,为此我们建议在项目中避免使用逼空运算符:
如果需要用到反射能力,可以使用代码生成思路实现,基于此思路也提供了相关的dart package: dart的反射
关于反射,有的语言默认全部方法支持反射,有的语言使用语法糖支持显式反射,而dart用代码生成方式支持反射(或者说不支持反射),确实比较出乎我的意料之外的。这说明2点,第一:dart重视性能和编译优化,第二:代码生成这种方式在dart体系中应多处出现。代码生成确实给了语言很大的扩展空间,dart编译器和运行时抛掉了反射,也可以更加专注于代码生成的优化和执行效率,也意味着坚实的走在类似C++极致性能的道路上(我也感觉是chrome里优化V8性能那波人被JavaScript的动态化折磨得不要不要的,为此在dart果断的砍掉了动态化的特性)。
因为要实现逻辑跨平台,我对Dart语言和其他语言的交互比较关注。Dart毕竟是一种全新的语言,无论设计理念多么先进都会苦于没有丰富的库,因此Dart也更注重和其他语言的通信。
Dart和C语言的交互比较直接:
Dart和Native (java/OC)交互提供了类型安全机制:
Pigeon是一个代码生成器工具,使Flutter和主机平台之间的通信安全,更轻松,更快捷。
果然,代码生成的思路体现在官方的不少库中。这也许也是从chromium里学到的经验吧,chromium里有大量通过脚本生成的代码。
Flutter框架使用的编程范式 (flutter.dev)
Flutter倾向于采取了最新的技术方案,其中UI界面的核心设计模式参考了React对UI开发的探索模型,这一点在Flutter wiki上有多处进行谈论:
对于习惯了传统的UI模型思维方式来说,这种UI开发模式确实需要一段时间的熟悉。不过这种声明式编程方式确实是一种进步的探索,我想从多个方面对此设计进行思考:
看上去和web的devtool看起来很像,感觉就是chromium里的devtool的后端,不过其本身是用dart实现的,这也体现出flutter对dart的开发效率的自信,这也让我更加坚定好好学习flutter。
如果对Flutter的设计原则深刻理解后,就会对Flutter很多细节的实现和方向的制定找到一定的内在联系:
拉下Flutter engine源码后,粗略看了一下,隐隐的觉得,flutter受chromium项目影响很深,甚至怀疑是同一拨人做出来的。
Build System是GN; 在源码里出现了大量的Copyright 20xx The Chromium Authors的版权声明:
Src目录下的gpu目录就是从chomium里copy出来然后删了不用的文件。
对比了一下flutter和chrome的DEPS文件,核心的库基本是一致的,能找到对应关系:
然后上网上查了一下flutter起源:
Flutter 的诞生其实比较有意思,Flutter 诞生于 Chrome 团队的一场内部实验, 谷歌的前端团队在把前端一些“乱七八糟“的规范去掉后,发现在基准测试里性能居然提高了 20 倍,机缘巧合下 Flutter 就这么被立项。
粗略浏览了一下源码,主要关注lib, runtime, shell三个文件夹即可:
想往flutter里加原生扩展,可以直接在DartIsolate::LoadLibraries添加扩展;想修改VM参数,在DartVM::DartVM构造函数实现。Flutter Engine代码组织清晰,可阅读性很高。让人看一眼就有定制一个的Flutter Engine的冲动。
目前我们的桌面客户端使用C++实现了逻辑跨平台,使用QT实现GUI跨平台。接下来,我们正在计划把APP项目使用Dart实现逻辑跨平台,使用Flutter实现GUI跨平台,最终实现课堂业务的一次开发多平台运行目标。
作为Flutter的初学者,上面很多想法不一定成熟,也期待能尽快成长成Flutter老鸟,思考更多关于Flutter的实践。
Flutter architectural overview | Flutter
带你全面了解 Flutter,它好在哪里?它的坑在哪里? 应该怎么学? - 专栏 - 声网 Agora RTC 开发者社区
Flutter vs Chromium 动画渲染的对比分析 - 知乎 (zhihu.com)
字节跳动为什么选用Flutter:并非跨平台终极之选,但它可能是不一样的未来 - Gityuan博客 | 袁辉辉的技术博客