vlambda博客
学习文章列表

Flutter并不像你想象中的那么完美

作者 | Bernardo Ferrari
译者 | 王强
编辑 | Yonie
近日,国内外都掀起了Flutter的学习热潮。本文作者分享了自己在学习Flutter时心得与体会。

免责声明:我是一名 Android 开发者,我用 Kotlin 写的项目在 GitHub 拿了 1000 颗星,我很喜欢 Kotlin。我讨厌 Android 、iOS 的UI,但我很期待 Swift UI 和 Compose UI……终于来了。

是个原生 Android 开发者都会骂几句 Flutter,目前在 GitHub 上它足足有 超过 7 千个未解决的问题,跟 Adobe Flash 一比就知道这是多吓人的数字了。但不管怎样,因为我之前在跨平台开发中吃了很多苦头,所以我还是决定学一学 Flutter,看看它能不能让我活得轻松一点。用户天天抱怨我的应用为什么不出 iOS 版本,而且 Flutter 很快就能支持 Web,我看我也没什么选择了。

Flutter并不像你想象中的那么完美

类似这种事情有必要吗?

这篇文章不会谈什么有状态 / 无状态小部件或者一般性的话题。我要讲的东西你几乎见不到有人会提,比如上面的截图这种事情。为什么连修复错误都要悬赏啊?

作为背景知识,你应该知道以下三件事:

  • 他们用 GitHub 中的点赞数量来确定问题的优先级。
  • “许多”非常重要的问题需要数月(甚至数年)才能解决,这实在让人郁闷——而且会导致令人很不爽的状况,上面的截图就是例子。
  • 你经常需要依赖第三方库,也许哪天这些库就没人继续维护了,但你也没别的选择。Flutter 不像 Android 上的 Square 或谷歌的 Jetpack,前者对社区的依赖程度要高得多,你躲都躲不开的。我不是说我就不喜欢开源或各种库——我很喜欢它们!但我每天回家都会看到有好些很有用的 Flutter 库上次更新时间都是 4-10 个月之前了;我也搞不清到底是这些库停止开发了呢?还是说作者准备在下次 Dart 更新时再同步更新。

安装过程很漫长

我说得有点夸张了。安装很慢!但不像在没有 Conda 的 Linux 上配置 TensorFlow 那么难。多谢 Reddit 的提醒!我修改了下,下面是改过的版本:

曾经我以为踏入 Flutter 世界的第一步会非常简单。很可惜,我错了。你得下载一个 zip,把 PATH 导出到正确的位置(只能设置为当前的终端会话),然后调用 flutter 命令来安装所有内容。然后你还得再输一些命令来安装剩下的工具才能在 iOS 中运行 Flutter 应用,或者要下载 Android Studio 来开发 Android 应用。在 iOS 上你得用 homebrew 再装一些库才行。

我自己还是希望能在 homebrew 里输一条命令就安装好整个 Flutter,而且还有人为此开了一个问题,实际上这个问题受欢迎度都到第: https://github.com/flutter/flutter/issues/14050

也能找到一些非官方脚本,有的很好用,也有的做得很差,但就算用了脚本也还是要手动做很多工作:你只能使用 flutter doctor 更新 Flutter,不能用 brew upgrade;想从稳定版升级到测试版基本上意味着要重装一遍,而且你还要搞清楚它装哪儿了,因为睿智的 Android Studio 会问你 Dart 编译器在哪里。最近的一项用户调查表明,“完善安装流程会带来更高的用户留存率”,所幸官方现在看起来很重视这个事情了。

好啦,那么终于安装完毕后我们可以开始学习 Flutter 了吧。结果大家才学了点 最基本的操作就得自谋出路了——简直和学习 Android 开发一个样儿。最后我花了些 dollar 参加了“基于 Dart 语言的 Flutter 开发完整流程训练营”,它还是“与谷歌 Flutter 团队合作建立的”,效果很好。如果你上了这条船那就去学学吧,对新、老程序员都很有帮助。

一团糟的 Material Design
排版

我是 Material Design 的忠实粉丝,我知道 headline6、subtitle1、body1 等等的正确用法。Android 和 iOS 的 Material Design 组件都有官方指南,表现很正常。但是 Flutter 的 MD 简直了。Flutter 里可以选择用旧命名的旧样式(默认)或者用旧命名的新样式你敢信?假设你选了新样式,那么看起来你是在用 body1,实际上你用的是 body2(反之亦然)。如果你要的是 headline5,结果得用 display1 才行。完全就是一锅粥啊。

Flutter并不像你想象中的那么完美

醒不来的噩梦

Bottom Sheet

我想用一个 Bottom Sheet 显示一个折叠视图,展开是个列表,向上滚动时又会折叠起来。这又不是什么稀罕物,谷歌地图之类的谷歌应用里都有这种东西。但就是做不到。Flutter 原生的 Bottom Sheet 功能太少,啥都干不了;非官方团队做的 Bottom Sheet 还好用些,但当列表位于顶部时,向下滚动页面它还是没法自己折叠起来。

图标

做一个图标好难!没有矢量绘图,没有 PDF 或 Lottie 支持(但有个连接 iOS Lottie 和 Android Lottie 的第三方库)。字体倒是有。你得把自定义图标打包到字体里。要么你只能用别人做的自定义图标打包的字体了。比如说 Flutter 的 Feather 图标包 上次更新是 10 个月前或 7 个月前 了,但人家本体上次更新是 两个月前的事。

如果你用的是 SVG(也需要 第三方库,还好作者是谷歌员工),它会异步加载成一张图像。比起直接用图标来说你得多做一点细微的工作,而且有的地方可能只支持图标,不过大体来说还是没什么问题的。SVG 唯一困扰我的问题就是它的异步属性:我见过连一个小部件都比 SVG 更早加载的情况,所以输出的结果会很奇怪,本来啥都没有,duang 的一下都冒出来了。

至于字体来说,如果你想用在 2018 年更新的 Material Design 图标的话可就不走运了。标准图标倒是能用,但如果你需要新的图标(sharp/outline/ 等等),就只能单独下载它们并构建成一个字体,或者找找看是不是有人已经造了 轮子,实在不行就单独下载下来用作 SVG。

文本输入

我在文本输入方面也遇到了一些问题,这方面的已知问题还一大堆(问题数量和其他组件差不多,但因为大多数应用都要用到文本输入,因此这类问题出现得更频繁,更烦人)。我最讨厌的一个问题是在特定情况下(经常出现)清除按钮用不了,如下所示。是的,这是个人问题,但由此可见多少细节都会出莫名其妙的错误,而且迟迟得不到解决。

Flutter并不像你想象中的那么完美

点击 X 清除文本字段时出错。1 个月前报告的问题。可稳定再现。https://github.com/flutter/flutter/issues/35848

其他烦心事
滚动监听器

我是 RecyclerView 的 addOnScrollListener 的重度用户,经常用在我的 Android 应用里。包括 Netflix 在内的许多应用都用它侦测用户的滚动操作,在页面滚动时隐藏键盘。但在 Flutter 上用它要花好大力气才行。当你使用 ListView 时列表会拦截拖动事件,因此手势回调什么都收不到。你可以监视列表的更改,但当列表更新 / 过滤 /……时会被调用,所以这条路子走不通。你还可以用一个监听器监听手指触摸屏幕的动作,真的很低级。我为此还提了一个 issue。此外还有个第三方库可以应付一部分人(特别是 iOS)的情况,但这就是另一回事了。

用户 filleduchaos 报告,PointerMoveEvents 可以提供 delta,因此当 GestureDetector 的 verticalDelta 不可用时可以用它对付一下,因为 Offset 既有垂直组件也有水平组件。相关链接: https://www.reddit.com/r/androiddev/comments/cm1o0v/from_android_dev_flutter_looks_good_but_is/evztf18/
滚动感知

滚动列表这么简单的行为也让人觉得“不对劲”,你会发现它和原生的就是不一样。也有人试图做些改进,甚至有一些集成测试对两者进行比较;但即使在 Android 上——而且 Android 是开源的,你也能感受到它们之间的区别。我不是说滚起来一个快一个慢,我只是说它们滚起来不一样,差异肉眼可见。React 的滚动也不太一样,但它更接近原生的感觉。

页面预览

在 Flutter 中做轮播只有一种方法,而且错误百出——而所有第三方库都只是打个包而已。如果你滚动得“太多”,它会跳过一个元素。你没法自定义,没法做出类似谷歌 Play 游戏中心那样的效果,因为它根本做不到。这里我也有一个未解决问题。可惜我恐怕要等好久了,因为去年 11 月的一个错误今年 6 月才刚修复。

状态

这个问题影响太重大了,甚至应该专门写一篇文章来批判。其中 Square 发布的这个问题就让我很郁闷: http://developer.squareup.com/blog/flutter-android-and-process-death

同时也告诉大家不了解 Android 或 iOS 的话可不要一头扎进 Flutter 里去。需要的平台还没搭好,到最后你还得处理别的问题。缺少 onSaveInstance 和其他一些东西也让人很痛苦。是的,这些东西在不同平台上的行为不一样,甚至在 Android 上总是在变化,但我还是希望 Flutter 将来能搞定一部分内容。

视图缩放

现在 Flutter 要支持 Web 端了,我真好奇他们要怎么解决这个问题:

Flutter并不像你想象中的那么完美

  总结  

看看社区,再看看第三方库,看起来相比 Android 来说 Flutter 跟 Javascript 走得更近。但 JS 正在一路狂奔,Flutter 还在原地徘徊,不知道下一步该往哪里走。宁可造成混乱也要保持兼容性?没错。一大堆水平堪忧的库刚面世就停止开发?就是这样。我很想爱 Flutter,但现在的 Flutter 不爱我啊。也许他们缺少人手,需要大幅扩张团队?也许他们只需要好好整顿一下,理清思路找出重点?问题究竟在哪儿只有他们自己才知道。

我还是会继续研究 Flutter,希望能用它开发一两个应用。用 Flutter 做 UI 还是很愉快的,虽说 Dart 还是有些不够用——而且我还没提依赖注入之类的高级玩意儿。就算发布应用不是什么轻松的工作,他们也花了差不多一年时间才做出来 32 位和 64 位的 APK。但愿他们别把心思都放在 Web 支持上吧,否则未解决问题很快就会堆到 1 万个以上了。

这篇文章的本意不是说“Flutter 问题多多,因此我讨厌它,它快死掉吧!”。本文的主题应该是“Flutter 并不完美,痛点显而易见而且越来越多,但如果他们多下点心思的话是能做出宣传的效果的”。我们过去很多年都在忍受 Android 上的一大堆缺陷,所以现在容忍 Flutter 没什么问题。但我真的希望它能比现在这慢吞吞的样子跑得再快些。

Flutter并不像你想象中的那么完美

我阅读一个库的源代码时偶然发现的注释来源: https://github.com/flutter/flutter/issues/17168

英文原文: https://medium.com/@bernaferrari/from-android-dev-flutter-looks-good-but-is-painful-here-are-my-frustrations-with-it-81b4bbe739f8

 活动推荐

前端位于研发的应用层,永远对迭代速度要求很高,同时又跟随业务在不断发展变化,团队也在快速发展和变化,工程化面临的挑战始终很大。在这个超级 APP 割据,又有大量后继挑战者的移动互联网后半场,没有最好的工程化方案,只有最适合的工程化方案。