学了将近3天的Flutter,准备弃坑了...

咱实话实说,Flutter真有这么香吗?看语言指数蹭蹭的涨,居然有人预测会超过RN,将来一统天下?

就这层层嵌套嵌套~写个UI就像绕迷宫,年龄大了,眼神不好真干不了这个。

一个好框架一开始就会让人不知不觉喜欢,记得当年第一次接触到Vue,一晚上就做了个demo,直接上手。

Dart是个好语言,但google能不能最起码把布局分开啊?算了~洗洗睡了,打算以后就老老实实RN+Electron撸了。玩不起。

大家有何高见?就这嵌套+样式布局不分离这一点。个人非常不看好Flutter

(大多数跨平台框架)上图这样的渲染过程,

貌似让接近原生般的跨平台应用构建变得简单,不过细节决定成败,由于依赖目标平台的组件进行渲染,这样就需要通过目标平台widget和框架widget数据同步的属性映射层,导致将每个动画映射到特定于平台的widget调用。

相比之下,Flutter不需要任何针对平台的UI组件去渲染其UI,它为了渲染应用用户界面的唯一前提就是canvas,类下图:

Flutter的渲染方式使其鹤立鸡群,消除了开发者对不同平台上UI一致性的任何担忧。

2.减少开发时间

根据我们的经验,构建一个普通的中型代码量Android应用也至少需要40秒才能交付到测试设备上;有时,调整布局中的较小外观可能需要花费很多时间。

有人可能会说:Android Studio为此提供了布局预览。但是,有一个缺点:该功能是有限的,并非总是能按预期运行,尤其是在使用自定义视图时。

Flutter的「热载入」功能又使你几乎可以立即看到已应用的更改,甚至不会丢失当前的应用状态。这正是利用flutter开发应用能够大大提速的原因。

Flutter团队投入大量精力为开发者提供各种现成的widget,很多widget甚至是可自定义的,这点与以往其他框架一样,又节省了你的时间;除了众多的核心布局widget之外,Flutter还提供了大量的Material和Cupertino小部件,可以完美的模仿每种设计语言的行为,大概工作原理如下:

归纳起来,使用Flutter,你会跳过应用开发中的几个超耗时的步骤。

3. 加快产品上线速度

在大多数情况下,与单独为Android和iOS开发的同一个应用相比较,Flutter应用所需的开发工时至少要少两倍。

原因简单:你不必单独为特定的平台去编写代码,就可以获得所需的视觉效果;任何基于2D的UI都可以在Flutter中实现,同时无需与本机应用扯上关系。

除此之外,Flutter还提供了用于构建UI的声明式API,可以显著提高性能,特别是涉及视觉调整相关的工作时,这个优势尤其突出。

4. 媲美原生

Flutter直接对接到了底层的绘制引擎,而不像RN得需要先转化成原生系统提供的UI组件,所以理论上来说Flutter在性能方面应该是等同于原生的,但是由于系统通常会对原生应用有著诸多的优化,所以也只能含蓄的用「媲美」一词。那么Flutter这样的设计也使得Flutter在多端一致性方面碾压其它跨平台方案。

5. 实现任何复杂、自定义动画UI

Flutter的最大优点之一是可以自定义屏幕上显示的任何内容,而不论它多么复杂。

尽管原生也可以实现自定义的UI,但对比起来所需的工作量投入是不同的。

下面是一个简单但自定义的UI的示例:

可以说,Flutter使该过程更加灵活和通用,也不会增加工作量。共享元素过渡,形状/颜色/阴影、剪切、过度, 这些都可以轻松实现。

6.独立渲染引擎

前面所说的,如果没有高性能的跨平台渲染引擎,上述功能大部分将无法实现。

Flutter使用Skia来渲染到平台提供的canvas上,由于有了高性能引擎,Flutter内置的UI几乎可以在任何平台上启动。换句话说,不再需要调整UI即可将其迁移到目标平台上,极大地简化了开发过程。

7. 针对平台的简单逻辑实现

除了UI外,许多当下移动应用非常依赖高级OS级别的功能,例如:获取GPS坐标、蓝牙通信、收集感测器数据、许可权处理等,而其中许多功能在开发Flutter应用时是可以通过Google提供的即用型插件去打通的。

当然,在某些情况下总会有无法提供的插件,Flutter也考虑到了,它的解决方案是,通过平台渠道在平台本机代码和Dart之间建立通信,这样的话,仅在原生方面付出一点额外的努力,你就可以在Flutter应用上实现原生应用可以执行的任何操作。

示例如下:

8. 已不仅仅是移动端

最后,你不仅可以在移动设备上进行Flutter应用开发,而且也有Flutter for Web和Flutter Desktop Embeddings。例如,在2020年的I/O会议上,Google展示了Flutter Web的技术前瞻,这使在浏览器中运行纯Flutter应用变成了可能,注意,这是无需修改源码的。


总结,Flutter和Dart语言的合璧,加之谷歌正在精心打造的Fuchsia操作系统,或许谷歌的野心是有一天让通过Flutter框架开发的应用运行在不同的智能设备上。

那么,恐怕不仅仅是「有人喜欢Flutter」,而是会有更多开发者加入利用这套框架进行应用开发的行列中。

编辑于 2020-12-30继续浏览内容知乎发现更大的世界打开Chrome继续闲鱼技术闲鱼技术?

已认证的官方帐号

长文预警,带大家重新认识一下Flutter。

Flutter也许不再是非常热门时髦的话题了,但作为一项已经逐渐进入规模化实践的技术,它的价值已经初步获得认可,后续应该有不错的生命力。作为较早期的Flutter实践者,我一直在思考Flutter的技术价值以及如何释放这些价值,本篇尝试从一个新的视角去结构化的梳理Flutter的技术价值并做对应的应用分析。这里不会涉及到Flutter具体领域的技术点,但是会结合我们团队过去的探索实践,在技术使用策略的层面做一些总结,希望能帮助到小伙伴们在开发实践中思考提炼,抬头看路,仰望星空,找到未来的创新方向。

一. 前端有些啥问题

要溯源Flutter, 就得从前端说起了。这里的前端是相对于后端的概念,大概泛指通过图形界面实现用户交互的终端技术。这个领域一直很有活力,伴随著互联网一路走来,很多新思路和新技术都有点眼花缭乱:上古的MVC已经不大提起了,老一辈的MVP,MVVM也逐渐暗淡,新一辈的Vue,Angular,React方兴未艾,还有Redux, Mobx, Hooks推波助澜。这些技术都像是一个个有感情的小生命,有的热情,有的文艺,有的高冷,十分热闹。也许你会想:它们都在说个啥?它们都想解决一个啥问题?

1. 节点,连接和网路

互联网是这一切存在的大背景,互联网有3个大要素:节点,连接和网路拓扑结构。每一个要素的进化都会给前端带来升级和变革:从PC互联网到移动互联网再到物联网是节点在进化;充满想像的5G时代是连接在进化;从中心化到分散式是网路拓扑结构在进化。前端的使命是让用户(人)高效的嵌入到网路之中,让人和设备融合为一个有生命的网路「节点」。

PS:网路模型可以适配到前端的很多场景,里面的「节点」可以代指手机设备,应用程序,进程,页面,甚至组件。

2. 节点与前端技术

前端技术是用户(人)与设备的粘合剂,让二者有机的构成一个网路节点。我尝试剖析下前端技术在节点中的形态:首先它需要提供界面给用户,并响应用户的交互;需要管理和远端节点的通信,交换信息;还需要管理当前节点的信息状态;最后,为了方便的嵌入到网路中,节点需要一个友好的「外观」,就是生命周期。生命周期描述了节点的诞生,消亡,所拥有的权益,和所承担的责任。

PS:这个分治模型也具有一定的通用性,可以适用在应用程序,页面,或者组件。

3. 前端要解决的问题

当然,前端技术作为一种软体技术,在日常的工程开发中也需要基础的构建部署支撑。那么,综合前面的讨论,前端要解决的基础要素问题有:

  • 远端通信
  • 界面管理
  • 生命周期
  • 状态管理
  • 构建部署

这里面生命周期管理是一个比较「隐形」的问题,它其实就是构建「外观」描述,也就是「组件化」。这些基础要素问题的结构关系大概是:

这几个基础要素问题的解决往往不能孤立的进行,在设计解决方案的时候需要彼此配合。前端领域的技术方案通常都会合并解决其中的几个问题,比如:React解决界面管理和生命周期;Vue解决了界面管理,状态管理,和生命周期;Redux专注解决状态管理;GraphQL,BFF,Serverless解决远端通信;webpack解决构建部等等...

那么,Flutter解决了什么问题?或者,Flutter可以解决哪些问题呢?

二. Flutter都有些啥

有趣的技术方案应该有自己旗帜鲜明的个性,做架构设计往往是遇到了独特的问题或者发现了更好的工具。因此,使用Flutter做解决方案的时候,应该梳理下Flutter都带来了些什么。一般来说,主要有Dart语言,Dart运行时(VM),GUI框架,和相关的开发构建工具。

1. Dart语言

Dart语言不好说有多优秀,总的来说是一门工程「友好」的现代语言。也许感觉平淡无奇,但官方在介绍Flutter的时候,还略有「骄傲」的展示了它的包容性:它能较为原生的支持声明式,过程式,面向对象,函数式,和响应式等业务场景,它给技术方案实现提供了很自由的范式空间,这是值得发掘和尝试的。结合我自己的实践,有几个点值得一说:

  • 支持类似「协程」处理(async/await/yield):Dart是单线程的,但是支持非同步。这一点需要在使用中去体会,不展开说,理解深了以后,可能对很多问题都有新解法。
  • 提供Stream:当你要进阶学习Flutter的时候,很多地方能见到它。它能做流式数据处理,函数组合,传输控制,属于进阶必知必会。
  • mixin特性:这是很有用的特性,尤其在架构设计方面。它提供了新的组合方式,在做功能组合的时候,Dart可以使用对象注入,或者高阶函数,或者mixin。

2. Dart-Runtime / VM

当你引入Flutter,你就有一个Dart-Runtime啦。当然,它本来的意义是支持Flutter运行的,然而就像JS的V8引擎一样,本来是用来支持H5页面的,后面的脑洞就越开越大了。当然Dart没有JS的动态能力(特殊的场合也可以),但它是跨端的,而且aot性能有保障,发掘空间较大,还能同时覆盖几乎所有场景,手机app开发,PC的构建部署,服务端,甚至serverless运行时。

3. Flutter应用开发框架

Flutter带来了高性能的跨平台GUI Framework,这没啥可说的,用就是了!但如果已经有了自己的开发生态,舍弃成本太大,又想「借用」下Flutter的技术优势,大概有几种方案:

  • 语言转换,基本上就是把其他语言的布局结果交给Flutter Framework。
  • 中层Framework介入,选择一棵树介入,这样对接面会小一些。
  • 底层Framework替换,整个替换掉Flutter Framework, 直接使用底层的Engine。

当然,还有一种方式就是混合开发了,需要实现混合栈管理,而且在1.22版本以后,Flutter升级了Navigator组件,提供了Navigator 2.0,这对混合开发是一个利好。

4. 开发构建工具

值得一提的是HotReload,谁用谁知道。热部署不仅界面开发需要,这是个通用需求,如果在服务端通过Dart实现一个,也是极好的。

Flutter的构建工具并无太多亮点,而且因为Dart语言在Flutter中不支持反射(产物太大,增加包体积),业务架构实现上很多需要依赖于编译时处理的技术,这对构建系统的能力有较大依赖的。换一个角度,因为这一领域尚没有成熟方案,加上Dart的工程「友好」,可能实现由一种语言来统一前端开发,后端开发,以及构建和部署,真做到了会很酷!

三. Flutter可以有些啥玩法

讨论前端要解决的几个基础要素问题,也讨论了Flutter带来的技术工具,结合这两点,看看利用Flutter都能做些啥。

1. 远端通信

「远端通信」是一个做了抽象的概念,具体形式会根据「节点」的定义不同而不同。可以是指物理设备之间的通信(手机与伺服器),也可以指模块之间(页面与另一个页面)的通信,还可以指组件之间(两个StatefulWidget之间)的通信。因为在Flutter中「一切皆是Widget」,所以简化的看,Flutter里面大概分为两种情形:面向伺服器的通信和组件(Widget)之间的通信。

  • 面向伺服器的通信:这方面有传统的Restful,GraphQL,还有兴起于「云原生」概念的Serverless。借助于Dart的能力延伸,Dart-Runtime可以成为Serverless的可选容器,那么前后两端都可以使用Dart来开发,如果再用Dart补足中间的构建部署pipeline,那么可以搭建出一个很「云原生」概念的应用程序开发流(dev flow):

Flutter的跨端能力结合云原生的弹性部署,前后端的实现可以放到一起,它们之间的调用也变得简单自然,有理由相信这会是一个高效的开发方式。闲鱼已经做了前期的探索,并在业务中尝试落地。

此外,GraphQL与Flutter也是值得尝试的组合,GraphQL和React范式在理念上很对味口,但是我们并没有尝试过。

  • 组件之间的通信:Flutter提供的基础业务编程组件是StatefulWidget和StatelessWidget,它们是按树形结构来组织的,并提供了InheritedWidget来支持它们之间的通信,在通信方式可以总结出3种:
    1. Notify型:通知/监听模式,Flutter提供了ValueNotifier和ChangeNotifier, 简单方便,适用于轻量信息通信,参见Provider。
      1. Transmission型:数据传输模式,Dart提供了Stream来支持这种模式。使用灵活,扩展方便,几乎是框架设计必备,参见BLoC。
        1. Invoke型: 介面调用模式,类似轻量RPC方式,在Flutter的应用架构设计中竟然很少见到。它确实有些重,但是有前面的模式没有的优势:它是双向的。

        2. 状态管理

        状态管理是个大问题,它由两个元素构成:状态和处理状态的逻辑。在代码实现上,状态就是数据,逻辑就是函数。当它们变得复杂的时候,解决的办法其实就是拆分,然后再合理的组合。我尝试从状态和逻辑的拆分选择上来列举所有可能的解法:

        • 1. 状态不拆,拆分逻辑: 这种做法的特点全局共用一个状态结构体对象,所有状态全部放在这个对象中,叫做「统一状态管理」。只有一个数据对象,就消除了各个处理逻辑之间信息共享问题,逻辑内部没有状态,变得非常的纯粹(比如纯函数来实现),再将逻辑以合适的方式组合成一个整体,实现上界限清晰,简单优雅,代表的方案就是Redux。 如果采用这种设计方案,推荐使用函数式风格来实现,这倒不是因为函数式「更高效」,「更优雅」之类的,而是它与函数式的思路十分的契合,在实现上更容易把握住思路。用面向对象来实现也并没有问题,最后的效果取决于你所面临的工程环境和用户。 这种状态管理好处显而易见:一处状态发生改变,不需要到处发事件同步。但是如果用在复杂大业务上面(比如一个有数十个页面流程的业务产品),状态必定是复杂的,状态结构体必然是庞大的。Redux的方式很好的管理了逻辑,如果要管理一个统一庞大的状态数据,也许内存级别的SQL是个不错的主意,GraphQL-Client给了我们启发,我们也正在尝试实践。

        • 2. 逻辑不拆,拆分状态: 我把这种叫做「步进状态管理」,实际上这类似于状态机模式。但如果要真正使用,状态必须是有限的,而且不能经常变动。这与互联网持续多变的业务需求实际是不符合的,所以采用这种方式的设计几乎没有。但在一些很严肃的业务场景中,比如交易流程,一旦定下来就不容易变动。这时,步进状态管理就很合适了。

        • 3. 同时拆分逻辑和状态: 这是容易想到方案,在更细的粒度上,将状态和它对应的处理逻辑拆分打包,变成更小的域(scope),然后统一协调这些子域(subModel),我把这种叫做「组合状态管理」。进一步的方案可以统一定义subModel的基础行为,然后引入调度器来协调管理它们,subModel之间还可以共享上下文来共享信息等等。 这种思路形式自由,可以采用的实现方式很多,经典的面向对象当然不在话下,scoped_model采用的就是这种思路,scoped_model实现的简单易懂,同时能力也比较有限。当然也可以采用函数式的方式,高阶函数+闭包也能很好的实现,但是圈内没有看到有相关的设计实现。还有一点,Dart提供了Mixin特性,通过这个特性,可以得到更简洁的实现方案。比如,可以沉淀很多特定的Model,然后通过with选择组合到业务Model中来(参考Flutter Framework中WidgetsBinding的实现)。目前flutter-hook在做这方面的探索,flutter-hook看起来有些迷惑,其核心就是利用了Dart的Mixin特性来组合状态。

        3. 界面管理

        Flutter使用了响应式UI,目的就是让业务开发减少界面的管理工作,只要提供好页面「描述」就行了。虽然Flutter内建了类似Virtual Dom的Diff机制,但是,做这个Diff也是要费性能的,如果我们在框架设计上能内建的把Diff工作提前到数据层,是不是可以提升性能呢?

        我们尝试了几种方法,受制于在Flutter中Dart不能反射,效果不理想,也许后续生态完善之后会有好的解法。

        在UI开发中,Flutter一直有一个隐隐的声音就是动态化,官方好像是「忽略」的,这里也不谈了。

        4. 生命周期

        Flutter通过StatefulWidget给业务开发提供了基础的生命周期管理。组件生命周期的设计是随著业务场景的不同而不同的,我自己的理解,设计生命周期要从两点出发:一是组件从诞生到消亡的时间线,二是组件在场景中所拥有的权益和所承担的责任。生命周期的扩展原点是StatefulWidget,因业务场景不同而扩展不同,很难展开讲。

        举个例子,如果使用原生Flutter开发(或者叫纯Flutter开发),StatefulWidget所提供的生命周期是足够的。但是如果要做混合开发,引入混合栈后,显然就不够用了。这时候就需要提供新的组件来扩展生命周期,更好的满足混合场景的开发。当时我在做混合栈的时候并没有能理解到这一点。

        四. 结语

        本篇从分析前端开发需要面对的几个基础核心问题入手,结合Flutter带来的技术工具,尝试结构化的分析Flutter在业务开发中可能的技术选择和探索方向。当然,技术同学既要仰望星空,还需要脚下看。

        对于Flutter开发中的热点技术问题,欢迎关注闲鱼技术公众号的其他文章,或者加入我们,和闲鱼一起做一点不一样的技术!

        发布于 01-22继续浏览内容知乎发现更大的世界打开Chrome继续暗落亭苦来暗落亭苦来这儿没有什么值得看的东西了

        我还真挺喜欢Flutter,也成功转职了。

        我觉得我没有成见,先从事Android,后来学React Native,再后来才学的Flutter。

        对比优劣,不多说,得罪人。但回答了题主的反问吧。

        代码嵌套从一开始是不太习惯,现在已经接受。

        原因大概有几点:

        1、一览代码并没有多少意义。改代码也好,改bug也好,不需要一览几百行代码。写好注释,快速找到控制项位置,其实真的要读要看的代码,不会太多。至于截图里的代码,一眼就能看出是什么在干什么了。可能开始不习惯。

        2、代码量在减少。我实际对比了下代码量,Flutter远远小于Android原生。

        估计题主是web出身,所以对强大的css熟悉了。我作为原生开发,被xml折磨已久。


        长文预警,带大家重新认识一下Flutter。

        Flutter也许不再是非常热门时髦的话题了,但作为一项已经逐渐进入规模化实践的技术,它的价值已经初步获得认可,后续应该有不错的生命力。作为较早期的Flutter实践者,我一直在思考Flutter的技术价值以及如何释放这些价值,本篇尝试从一个新的视角去结构化的梳理Flutter的技术价值并做对应的应用分析。这里不会涉及到Flutter具体领域的技术点,但是会结合我们团队过去的探索实践,在技术使用策略的层面做一些总结,希望能帮助到小伙伴们在开发实践中思考提炼,抬头看路,仰望星空,找到未来的创新方向。

        一. 前端有些啥问题

        要溯源Flutter, 就得从前端说起了。这里的前端是相对于后端的概念,大概泛指通过图形界面实现用户交互的终端技术。这个领域一直很有活力,伴随著互联网一路走来,很多新思路和新技术都有点眼花缭乱:上古的MVC已经不大提起了,老一辈的MVP,MVVM也逐渐暗淡,新一辈的Vue,Angular,React方兴未艾,还有Redux, Mobx, Hooks推波助澜。这些技术都像是一个个有感情的小生命,有的热情,有的文艺,有的高冷,十分热闹。也许你会想:它们都在说个啥?它们都想解决一个啥问题?

        1. 节点,连接和网路

        互联网是这一切存在的大背景,互联网有3个大要素:节点,连接和网路拓扑结构。每一个要素的进化都会给前端带来升级和变革:从PC互联网到移动互联网再到物联网是节点在进化;充满想像的5G时代是连接在进化;从中心化到分散式是网路拓扑结构在进化。前端的使命是让用户(人)高效的嵌入到网路之中,让人和设备融合为一个有生命的网路「节点」。

        PS:网路模型可以适配到前端的很多场景,里面的「节点」可以代指手机设备,应用程序,进程,页面,甚至组件。

        2. 节点与前端技术

        前端技术是用户(人)与设备的粘合剂,让二者有机的构成一个网路节点。我尝试剖析下前端技术在节点中的形态:首先它需要提供界面给用户,并响应用户的交互;需要管理和远端节点的通信,交换信息;还需要管理当前节点的信息状态;最后,为了方便的嵌入到网路中,节点需要一个友好的「外观」,就是生命周期。生命周期描述了节点的诞生,消亡,所拥有的权益,和所承担的责任。

        PS:这个分治模型也具有一定的通用性,可以适用在应用程序,页面,或者组件。

        3. 前端要解决的问题

        当然,前端技术作为一种软体技术,在日常的工程开发中也需要基础的构建部署支撑。那么,综合前面的讨论,前端要解决的基础要素问题有:

        • 远端通信
        • 界面管理
        • 生命周期
        • 状态管理
        • 构建部署

        这里面生命周期管理是一个比较「隐形」的问题,它其实就是构建「外观」描述,也就是「组件化」。这些基础要素问题的结构关系大概是:

        这几个基础要素问题的解决往往不能孤立的进行,在设计解决方案的时候需要彼此配合。前端领域的技术方案通常都会合并解决其中的几个问题,比如:React解决界面管理和生命周期;Vue解决了界面管理,状态管理,和生命周期;Redux专注解决状态管理;GraphQL,BFF,Serverless解决远端通信;webpack解决构建部等等...

        那么,Flutter解决了什么问题?或者,Flutter可以解决哪些问题呢?

        二. Flutter都有些啥

        有趣的技术方案应该有自己旗帜鲜明的个性,做架构设计往往是遇到了独特的问题或者发现了更好的工具。因此,使用Flutter做解决方案的时候,应该梳理下Flutter都带来了些什么。一般来说,主要有Dart语言,Dart运行时(VM),GUI框架,和相关的开发构建工具。

        1. Dart语言

        Dart语言不好说有多优秀,总的来说是一门工程「友好」的现代语言。也许感觉平淡无奇,但官方在介绍Flutter的时候,还略有「骄傲」的展示了它的包容性:它能较为原生的支持声明式,过程式,面向对象,函数式,和响应式等业务场景,它给技术方案实现提供了很自由的范式空间,这是值得发掘和尝试的。结合我自己的实践,有几个点值得一说:

        • 支持类似「协程」处理(async/await/yield):Dart是单线程的,但是支持非同步。这一点需要在使用中去体会,不展开说,理解深了以后,可能对很多问题都有新解法。
        • 提供Stream:当你要进阶学习Flutter的时候,很多地方能见到它。它能做流式数据处理,函数组合,传输控制,属于进阶必知必会。
        • mixin特性:这是很有用的特性,尤其在架构设计方面。它提供了新的组合方式,在做功能组合的时候,Dart可以使用对象注入,或者高阶函数,或者mixin。

        2. Dart-Runtime / VM

        当你引入Flutter,你就有一个Dart-Runtime啦。当然,它本来的意义是支持Flutter运行的,然而就像JS的V8引擎一样,本来是用来支持H5页面的,后面的脑洞就越开越大了。当然Dart没有JS的动态能力(特殊的场合也可以),但它是跨端的,而且aot性能有保障,发掘空间较大,还能同时覆盖几乎所有场景,手机app开发,PC的构建部署,服务端,甚至serverless运行时。

        3. Flutter应用开发框架

        Flutter带来了高性能的跨平台GUI Framework,这没啥可说的,用就是了!但如果已经有了自己的开发生态,舍弃成本太大,又想「借用」下Flutter的技术优势,大概有几种方案:

        • 语言转换,基本上就是把其他语言的布局结果交给Flutter Framework。
        • 中层Framework介入,选择一棵树介入,这样对接面会小一些。
        • 底层Framework替换,整个替换掉Flutter Framework, 直接使用底层的Engine。

        当然,还有一种方式就是混合开发了,需要实现混合栈管理,而且在1.22版本以后,Flutter升级了Navigator组件,提供了Navigator 2.0,这对混合开发是一个利好。

        4. 开发构建工具

        值得一提的是HotReload,谁用谁知道。热部署不仅界面开发需要,这是个通用需求,如果在服务端通过Dart实现一个,也是极好的。

        Flutter的构建工具并无太多亮点,而且因为Dart语言在Flutter中不支持反射(产物太大,增加包体积),业务架构实现上很多需要依赖于编译时处理的技术,这对构建系统的能力有较大依赖的。换一个角度,因为这一领域尚没有成熟方案,加上Dart的工程「友好」,可能实现由一种语言来统一前端开发,后端开发,以及构建和部署,真做到了会很酷!

        三. Flutter可以有些啥玩法

        讨论前端要解决的几个基础要素问题,也讨论了Flutter带来的技术工具,结合这两点,看看利用Flutter都能做些啥。

        1. 远端通信

        「远端通信」是一个做了抽象的概念,具体形式会根据「节点」的定义不同而不同。可以是指物理设备之间的通信(手机与伺服器),也可以指模块之间(页面与另一个页面)的通信,还可以指组件之间(两个StatefulWidget之间)的通信。因为在Flutter中「一切皆是Widget」,所以简化的看,Flutter里面大概分为两种情形:面向伺服器的通信和组件(Widget)之间的通信。

        • 面向伺服器的通信:这方面有传统的Restful,GraphQL,还有兴起于「云原生」概念的Serverless。借助于Dart的能力延伸,Dart-Runtime可以成为Serverless的可选容器,那么前后两端都可以使用Dart来开发,如果再用Dart补足中间的构建部署pipeline,那么可以搭建出一个很「云原生」概念的应用程序开发流(dev flow):

        Flutter的跨端能力结合云原生的弹性部署,前后端的实现可以放到一起,它们之间的调用也变得简单自然,有理由相信这会是一个高效的开发方式。闲鱼已经做了前期的探索,并在业务中尝试落地。

        此外,GraphQL与Flutter也是值得尝试的组合,GraphQL和React范式在理念上很对味口,但是我们并没有尝试过。

        • 组件之间的通信:Flutter提供的基础业务编程组件是StatefulWidget和StatelessWidget,它们是按树形结构来组织的,并提供了InheritedWidget来支持它们之间的通信,在通信方式可以总结出3种:
          1. Notify型:通知/监听模式,Flutter提供了ValueNotifier和ChangeNotifier, 简单方便,适用于轻量信息通信,参见Provider。
            1. Transmission型:数据传输模式,Dart提供了Stream来支持这种模式。使用灵活,扩展方便,几乎是框架设计必备,参见BLoC。
              1. Invoke型: 介面调用模式,类似轻量RPC方式,在Flutter的应用架构设计中竟然很少见到。它确实有些重,但是有前面的模式没有的优势:它是双向的。

              2. 状态管理

              状态管理是个大问题,它由两个元素构成:状态和处理状态的逻辑。在代码实现上,状态就是数据,逻辑就是函数。当它们变得复杂的时候,解决的办法其实就是拆分,然后再合理的组合。我尝试从状态和逻辑的拆分选择上来列举所有可能的解法:

              • 1. 状态不拆,拆分逻辑: 这种做法的特点全局共用一个状态结构体对象,所有状态全部放在这个对象中,叫做「统一状态管理」。只有一个数据对象,就消除了各个处理逻辑之间信息共享问题,逻辑内部没有状态,变得非常的纯粹(比如纯函数来实现),再将逻辑以合适的方式组合成一个整体,实现上界限清晰,简单优雅,代表的方案就是Redux。 如果采用这种设计方案,推荐使用函数式风格来实现,这倒不是因为函数式「更高效」,「更优雅」之类的,而是它与函数式的思路十分的契合,在实现上更容易把握住思路。用面向对象来实现也并没有问题,最后的效果取决于你所面临的工程环境和用户。 这种状态管理好处显而易见:一处状态发生改变,不需要到处发事件同步。但是如果用在复杂大业务上面(比如一个有数十个页面流程的业务产品),状态必定是复杂的,状态结构体必然是庞大的。Redux的方式很好的管理了逻辑,如果要管理一个统一庞大的状态数据,也许内存级别的SQL是个不错的主意,GraphQL-Client给了我们启发,我们也正在尝试实践。

              • 2. 逻辑不拆,拆分状态: 我把这种叫做「步进状态管理」,实际上这类似于状态机模式。但如果要真正使用,状态必须是有限的,而且不能经常变动。这与互联网持续多变的业务需求实际是不符合的,所以采用这种方式的设计几乎没有。但在一些很严肃的业务场景中,比如交易流程,一旦定下来就不容易变动。这时,步进状态管理就很合适了。

              • 3. 同时拆分逻辑和状态: 这是容易想到方案,在更细的粒度上,将状态和它对应的处理逻辑拆分打包,变成更小的域(scope),然后统一协调这些子域(subModel),我把这种叫做「组合状态管理」。进一步的方案可以统一定义subModel的基础行为,然后引入调度器来协调管理它们,subModel之间还可以共享上下文来共享信息等等。 这种思路形式自由,可以采用的实现方式很多,经典的面向对象当然不在话下,scoped_model采用的就是这种思路,scoped_model实现的简单易懂,同时能力也比较有限。当然也可以采用函数式的方式,高阶函数+闭包也能很好的实现,但是圈内没有看到有相关的设计实现。还有一点,Dart提供了Mixin特性,通过这个特性,可以得到更简洁的实现方案。比如,可以沉淀很多特定的Model,然后通过with选择组合到业务Model中来(参考Flutter Framework中WidgetsBinding的实现)。目前flutter-hook在做这方面的探索,flutter-hook看起来有些迷惑,其核心就是利用了Dart的Mixin特性来组合状态。

              3. 界面管理

              Flutter使用了响应式UI,目的就是让业务开发减少界面的管理工作,只要提供好页面「描述」就行了。虽然Flutter内建了类似Virtual Dom的Diff机制,但是,做这个Diff也是要费性能的,如果我们在框架设计上能内建的把Diff工作提前到数据层,是不是可以提升性能呢?

              我们尝试了几种方法,受制于在Flutter中Dart不能反射,效果不理想,也许后续生态完善之后会有好的解法。

              在UI开发中,Flutter一直有一个隐隐的声音就是动态化,官方好像是「忽略」的,这里也不谈了。

              4. 生命周期

              Flutter通过StatefulWidget给业务开发提供了基础的生命周期管理。组件生命周期的设计是随著业务场景的不同而不同的,我自己的理解,设计生命周期要从两点出发:一是组件从诞生到消亡的时间线,二是组件在场景中所拥有的权益和所承担的责任。生命周期的扩展原点是StatefulWidget,因业务场景不同而扩展不同,很难展开讲。

              举个例子,如果使用原生Flutter开发(或者叫纯Flutter开发),StatefulWidget所提供的生命周期是足够的。但是如果要做混合开发,引入混合栈后,显然就不够用了。这时候就需要提供新的组件来扩展生命周期,更好的满足混合场景的开发。当时我在做混合栈的时候并没有能理解到这一点。

              四. 结语

              本篇从分析前端开发需要面对的几个基础核心问题入手,结合Flutter带来的技术工具,尝试结构化的分析Flutter在业务开发中可能的技术选择和探索方向。当然,技术同学既要仰望星空,还需要脚下看。

              对于Flutter开发中的热点技术问题,欢迎关注闲鱼技术公众号的其他文章,或者加入我们,和闲鱼一起做一点不一样的技术!

              发布于 01-22继续浏览内容知乎发现更大的世界打开Chrome继续暗落亭苦来暗落亭苦来这儿没有什么值得看的东西了

              我还真挺喜欢Flutter,也成功转职了。

              我觉得我没有成见,先从事Android,后来学React Native,再后来才学的Flutter。

              对比优劣,不多说,得罪人。但回答了题主的反问吧。

              代码嵌套从一开始是不太习惯,现在已经接受。

              原因大概有几点:

              1、一览代码并没有多少意义。改代码也好,改bug也好,不需要一览几百行代码。写好注释,快速找到控制项位置,其实真的要读要看的代码,不会太多。至于截图里的代码,一眼就能看出是什么在干什么了。可能开始不习惯。

              2、代码量在减少。我实际对比了下代码量,Flutter远远小于Android原生。

              估计题主是web出身,所以对强大的css熟悉了。我作为原生开发,被xml折磨已久。


              我还真挺喜欢Flutter,也成功转职了。

              我觉得我没有成见,先从事Android,后来学React Native,再后来才学的Flutter。

              对比优劣,不多说,得罪人。但回答了题主的反问吧。

              代码嵌套从一开始是不太习惯,现在已经接受。

              原因大概有几点:

              1、一览代码并没有多少意义。改代码也好,改bug也好,不需要一览几百行代码。写好注释,快速找到控制项位置,其实真的要读要看的代码,不会太多。至于截图里的代码,一眼就能看出是什么在干什么了。可能开始不习惯。

              2、代码量在减少。我实际对比了下代码量,Flutter远远小于Android原生。

              估计题主是web出身,所以对强大的css熟悉了。我作为原生开发,被xml折磨已久。


              我们小团队的实际flutter项目,三个工具app,一个阅读app,一个聊天app,一个解谜小游戏。

              全部双端上线(游戏暂时没版号只上了iOS )

              减少一半的开发工作量。最最最重要的是性能和原生几乎没有差别,除了前两个项目出现其他回答中的无厘头崩溃(基本是原生crash或者dispose后setState出问题),后面几个app都比较顺利,我们是从flutter 1.5.* 开始接触的,当时为了给app加广告整整搞了一个星期,现在已经很nice了,platform view好用。

              嗯,flutter真的香,嵌套UI代码是个问题,不过 IDE 应该都有wrap 和 extract ,也比较容易解决这个问题。接受这种设定后,你会发现写起来很带感。github上这么火的情况下,建议不要只看个表面就做出判断。


              因为暂时没更好的选择,其实很多人喜欢flutter不是喜欢dart,而是喜欢skia。


              推荐阅读:
              相关文章