【开发经验】浅谈flutter的优点与缺点

13
本文默认你已经是开发者,并对Flutter有基本的了解,但是还未深入使用,希望了解Flutter在商业级(而非demo)的项目中的优势与劣势。

很多前端开发者应该都寻找过跨平台的App解决方案,包括没有同时独立开发iOSAndroid双端原生app的开发者,应该都接触过或者看到过Google的Flutter框架。我对于iOS原生开发与基于Vue.js的web开发比较熟悉,并在一个正在进行的蓝牙硬件项目中应用了Flutter框架,经历的漫长的适应,在本文中我将以iOS原生开发者与web开发者的视角看待Flutter框架,简单罗列Flutter的优势与缺点。

Flutter优点

Flutter的优点非常明显,如果你选择一个跨平台框架,与众多基于html的跨平台框架相比,Flutter绝对是体验最好,性能与构建思路几乎最接近原生开发的框架。

  • 性能强大,流畅

Flutter对比weexreact native相比,性能的强大是有目共睹的。基于dom树渲染原生组件,很难与直接在原生视图上绘图比肩性能,Google作为一个轮子大厂,直接在两个平台上重写了各自的UIKit,对接到平台底层,减少UI层的多层转换,UI性能可以比肩原生,这个优势在滑动播放动画时尤为明显。

  • 路由设计优秀

Flutter的路由传值非常方便,push一个路由,会返回一个Future对象(也就是Promise对象),使用await或者.then就可以在目标路由pop,回到当前页面时收到返回值。这个反向传值的设计基本是甩了微信小程序一条街了。弹出dialog等一些操作也是使用的路由方法,几乎不用担心出现传值困难

  • 单例模式

Flutter支持单例模式,单例模式的实现也非常简单。单例模式很好的解决了一些问题。相比之下,js的单例则并不是一个真正的单例,或者说不是一个简单的单例,这也是受限于js所运行的环境。单例模式并不总是合理的,容易被滥用。但是在App的初期开发中,往往一个容易实现的单例可以帮助我们快速完成一些逻辑的搭建。

  • 优秀的动画设计

Flutter的动画简单到不可思议,动画对象会根据屏幕刷新率每秒产生很多个(一般是60个)浮点数,只需要将一个组件属性通过补间(Tween)关联到动画对象上,Flutter会确保在每一帧渲染正确的组件,从而形成连贯的动画。这种十分暴力的操作在Flutter上却看不到明显的卡顿,这也是Flutter的一个魔力所在。相比之下其他跨平台框架几乎不能设计动画……往往会遭遇非常严重的性能问题。

  • UI跨平台稳定

Google直接在两个平台上在底层重写了UIKit,不依赖于Css等外部解释器,几乎不存在UI表达不理想,渲染不正常的情况,可以获得非常稳定的UI表达效果。Css换个浏览器就有不同的表现,基于Css的跨平台框架很难获得稳定的UI表现。

  • 可选静态的语言,语言特性优秀

Dart是一个静态语言,这也是相对于js的一个优势。Dart可以被编译成js,但是看起来更像java。静态语言可以避免错误,获得更多的编辑器提示词,极大的增加可维护性。很多js库也已经用ts重写了,Vue3.0的底层也将全部使用ts编写,静态语言的优势不言而喻。

Flutter缺点

  • 假装跨平台,躲不开原生代码

这是最大的问题,跨平台框架说白了就是UI跨平台,最后还是在原生平台运行,本来两个平台就有天壤之别,一套代码就想吃掉iOS和Android在实际应用之中其实根本就不现实。Flutter具有与原生代码互相调用的能力固然非常科学,但是问题反而显得更加明显——我一个前端工程师上哪里去知道什么是UIViewController,什么是Activity呢?我要是双端都熟悉,学习Flutter就显得很没有必要。这是一个很矛盾的点,特别是在团队里,只有几个前端突然想学Flutter,是绝对做不来大项目的,如果有原生开发者,那就没必要搞Flutter了。

  • 组合而不是继承的思路

Flutter提倡“组合”,而不是“继承”。在iOS开发中,我们经常会继承UIView,重写UIView的某个生命周期函数,再添加一些方法和属性,来完成一个自定义的View。但是在Flutter中这些都是不可能的——属性都是final的,例如你继承了了一个Container,你是不能在它的生命周期中修改他的属性的。你始终需要嵌套组合几种Widget,例如RowContainerListViewWidget。这种方法非常不符合直觉,初学时很难想明白如何构建一个完整的组件。

  • Widget的类型难以选择

FlutterWidget分为StatefulWidgetStatelessWidget两种,一种是带状态的一种是不带状态的,刚开发的时候很难想明白用哪个,因为StatelessWidget也能存值,其实区别就在于框架重构UI的时候会使用State来重构,如果是StatelessWidget,暂时存进去的值就没了。但是问题远不止这么简单,好在只是有点麻烦,并不影响产品性能。

  • 糟糕的UI控件API

虽然google尽可能的让我们通过构造函数定制化Widget,但是也难免有遗漏的。例如,又一次我想修改一个Appbar的高度,居然没有找到关于高度的属性,通过阅读源码发现,高度是写死(const)的。上文已经说过,无法通过生命周期来改变组件属性,自己写Appbar显得非常没必要,毕竟我还是想使用Appbar的各种方便的功能。最后我只能把他的源码全部复制出来,直接修改高度来使用。初学框架,和一些初级开发者是不可能有迅速阅读源码的能力的(作为框架也不应该产生如此问题)。一些定制化的UI的Api设计经常有缺失,好在我已经基本习惯了。除了Appbar这种复杂的组件,自己写一个小组件也并不费事。

  • 糟糕的资源管理设计(已解决)

这里是最蠢的,Flutter支持动态加载不同分辨率的图片,但是目录设计太鬼畜了。简单的说,Sketch导出的多分辨率资源,几乎不可能直接拖到Flutter里用,极其,极其,麻烦。

为了解决这个问题我编写了一个node脚本工具fmaker,用来管理多分辨率资源,顺便生成app图标:
使用帮助/仓库地址:【Flutter工具】fmaker:自动生成倍率切图/自动更换App图标

毕竟国情在此,要用Flutter,先买梯子。虽然有“在中国使用Flutter”指南,但是太麻烦,没梯子开发Flutter,难度系数太高了,总不能碰到每个问题都花一整天寻找替代方案吧,先买好梯子图个安心……

总结

Flutter主要的坑就在于需要非常了解原生的环境,其实跨平台的框架都是如此,想要通过跨平台的API就拿下双端的开发任务,对认真学习的原生开发者来说也是不公平的。
主要的优势则在于动画流畅,很多开发者反应比原生安卓还流畅(存疑),至少在iOS上是看不到卡顿的,安卓上动画也很稳定,性能上展示了Google的硬实力

本人是iOS原生开发者,亦熟悉Vue.js,小程序等前端开发,对Android开发与Reactive Naive不甚了解,本文乃是一些初级经验与感悟,若有不当还请评论指正。

本文禁止任何形式转载。

你可能感兴趣的

29 条评论
david · 3月19日

作者好,想请教个问题。
先说下场景,我们公司app说复杂也不复杂,但是业务逻辑比较复杂,尤其是两端开发人员在没理解透业务逻辑的情况下很容易导致写出的功能不符合要求,或者只有一端符合要求。所以我是在想个别模块如果业务逻辑比较复杂可以使用一个“中间件”(可能用词不太准确)的技术,就比方说flutter,然后嵌入到项目里面去,这样app大部分还是原生,少部分逻辑复的模块采用这种“中间件”去开发。
不知道flutter能不能实现这种场景。期待各位大佬的回答。

+1 回复

0

如果只是逻辑复杂,而不是依赖原生的很多东西(例如做即时通讯App使用的框架没有Flutter版本),Flutter是可以全部做下来的。如果一定要混编,技术上是可以实现的,但是目前我也没有试过,你可以看一看这篇文章 https://www.jianshu.com/p/48a...。相信会对你有所帮助。

马嘉伦 作者 · 3月19日
0

楼主,Flutter不适合做即时通讯吗?会有什么问题呢?

AlexJoo · 6月21日
0

@AlexJoo 主要是没有成熟的库可以用,自己写太慢了

马嘉伦 作者 · 6月21日
FrankHe · 5月22日

分享一个 不错的Flutter 库列表: https://flutterawesome.com/

+1 回复

badbad小哥哥 · 2018年12月17日

Flutter具有与原生代码互相调用的能力固然非常科学,但是问题反而显得更加明显——我一个前端工程师上哪里去知道什么是UIViewController,什么是Activity呢?我要是双端都熟悉,学习Flutter就显得很没有必要。这是一个很矛盾的点,特别是在团队里,只有几个前端突然想学Flutter,是绝对做不来大项目的,如果有原生开发者,那就没必要搞Flutter了。
我也有如此疑问。。。

回复

0

唉,不提了,因为一个很底层的bug,把一个Flutter库的安卓代码都看了一遍,修好了bug,现在感觉我都会写安卓了😂。

马嘉伦 作者 · 2018年12月18日
1

@马嘉伦 兄弟,马加爵跟你什么关系

小西note · 3月21日
0

@小西note 他和我什么关系我不知道,我大学室友对我可好了

马嘉伦 作者 · 5月17日
小黑马 · 1月7日

初次接触 Flutter,感觉非常不友好。示例代码 无数排列整齐的括号 不停的暗示我,Flutter的项目里面充满了 死亡回调。
React Native 初次接触则感觉良好,成熟的 JS语言,然后调试又麻烦,有服务窗口,还要开 chrome调试。

回复

0

前端可以搞RN,不过原生环境必须了解了才行。

马嘉伦 作者 · 1月7日
0

经过团队实操,RN的坑远大于Flutter的几个括号,所以还是Flutter比较稳定。我计划写一篇文章,讲一下从谷歌的UI源码来看如何避免反括号太多影响阅读的问题。

马嘉伦 作者 · 5月17日
0

你好,我已经写了一篇文章讲如何避免反括号太多 https://segmentfault.com/a/11...

马嘉伦 作者 · 7月17日
Free · 1月8日

我ios和安卓双端都会,有必要搞flutter吗?想想要踩这么多坑就不太想学...复杂app要涉及到音视频转码解码还有地图sdk,想想到时候要各种找轮子各种channel就各种烦。

回复

0

这东西写ui快,动画和路由都简单,项目里原生代码不多的时候可以用在小项目里,极大提升效率。

马嘉伦 作者 · 1月9日
0

赞同楼主的看法,看情况选择开发语言。如果项目中是简单的增删改查业务数据的话,使用RN或者Flutter比较极大提供开发效率

使劲挤海绵 · 1月16日
bacy · 2月28日

Fuchsia不商用,它就永远只是个demo

回复

0

这可不一定,老板又不懂技术,只要看到体验好(流畅),开发比原生效率高,为了效益还是有可能选择flutter的,毕竟现在RN性能有问题,不能做复杂设计。

马嘉伦 作者 · 2月28日
hahand · 4月2日

即使如rn,放到现在做项目依然是各种坑,何况是才出的flutter ?rn和flutter只适合开发比小程序体量略大的app或者接外包这种一次性代码。对于大企业而言,开发成本和维护成本会比原生高的多。

回复

0

大厂全部都是原生加自己的动态框架的,轮子随便造。小公司比不了,大多数项目其实都是快消品,不然也不会出现这么多框架。

马嘉伦 作者 · 4月2日
cheng_57dde6bd72698 · 4月4日

一致纠结于Flutter还是Xamarin.Forms。后来发现Xamarin.Forms有更多的案例,而且Xamarin.Forms4.0提供了Shell ,搭配VS2019竟然比Flutter更爽。不知道是不是错觉,有种无法自拔的感觉。

回复

0

C#太难学了,Dart好上手很多

马嘉伦 作者 · 4月10日
小赵同学 · 4月17日

你说的缺点,感觉没说到点上,也就是说,你说的缺点不能称之为缺点,真正的缺点你并没看到。伪跨平台,这才是flutter的独到之处,只有转化为原生,才能达到最流畅效果,这是优点,绝非缺点。组合和修改ui控件,各有优势,这里你说的,可能是谷歌官方没有完善各个控件高度自控能力,个人觉得,组合和修改并无区别,只是你个人习惯了修改而已,而且,对于flutter来说,fluttet的widget正是其高明之处,这应该是优点!

回复

0

等你不得不写原生代码就有体会了……伪跨平台主要是团队开发的时候容易碰壁,要求团队要懂双端开发,还要额外学个flutter。成本很高的。
至于说组合与继承这个,继承确实比较笨重,组合widget的思维还是需要学习一段时间的,上手没那么快。我读了几天源码才比较适应。

马嘉伦 作者 · 4月18日
桔子和猫 · 4月18日

楼主, appbar的高度这个, flutter是可以直接改sdk源码的啊, 找到那个const字段, 直接改不就得了

回复

0

这个和npm或者cocoapod包一个道理,你github传上去,换个电脑install就无效了……一定要复制出来改,不然就要把整个flutter依赖放git上,得不偿失啊。

马嘉伦 作者 · 4月18日
随风漂流 · 4月23日

事实胜于雄辩,flutter现在火得一塌糊涂...

回复

载入中...