头图

哈喽,我是老刘

我本人是带客户端团队的,带着团队切换到Flutter上也已经差不多6年了。
但也不是只写客户端App。基于Flutter来说,也写过桌面端、Web端程序。
但是坦白说,真没有一个Flutter项目是同时覆盖6个平台的。

为啥呢?
我觉得很多人理解的夸6个平台可能是个伪命题。

大多数项目不具备跨越6个平台的资格

来看看我们常用的软件
微信
最开始有个web端,后来被放弃了,现在只有手机端和桌面端
支付宝
好像主要就是手机端
爱优腾等
手机端、Web端倒是比较全,但是桌面端就不怎么全了。

其它的我就不一一列举了。
你看即使是那些国民级的应用,也没有横跨6个平台的。
我自己用的软件中,真正横跨六个平台的好像只有Obsidian。
但是Obsidian的内核是web技术,只不过在PC端基于Electron而移动端基于Capacitor。
所以某种程度上可以理解为在6个端,分别给web内核套了一个不同的壳。

为什么极少有软件横跨6个平台呢?
我觉得大致上有三类原因
1、应用场景不需要
比如像支付宝这样的软件,主要的应用场景就在手机上,开发pc端的价值不高。
2Web端可以代替桌面端
目前PC上浏览器的性能和流畅性都已经非常好了。
所以除了少数交互非常重的软件外,大多数以信息展示为主的软件都可以在Web端流畅运行。
而且PWA和Webassemble两种技术又进一步提升了Web的覆盖范围。
如果用户不需要安装单独的软件就可以得到足够好的使用体验,而开发者也不需要发布新版本就可以更新功能,那是不是比单独开发一个PC端好得多呢?
3、开发成本太高
想想原先开发手机端App
即使只有Android和iOS两个平台,公司需要养两个团队。
而开发中也经常会因为两个平台的差异,需要协调开发进度、资源等不同平台带来的问题。
如果想要同时维护6个平台的原生开发,复杂度和成本怕是要几何量级提高。
即使是使用Flutter这样平台一致性极高的跨平台框架,仍然难以避免在不同平台进行适配。
比如Android上有系统级的侧滑返回按钮,iOS平台上就没有完全对应的操作。

对大多数产品来说,即使是用Flutter开发,如果要支撑覆盖六个平台的成本。
也需要产品的用户规模足够的大。
但是又有多少个产品能有机会成长到这一步呢?

好的,如果说同时覆盖6个平台在大多数时候是个伪命题,那Flutter能够一次开发6个平台运行的意义在哪里?

单类平台跨多个端

比如Android和iOS
Windows、linux和Mac

其实对所有的跨平台开发框架来说,这种场景都是最好的。
因为它规避了一个最大的问题,就是不同类型的平台其UI、功能是不完全一样的。

比如同样是视频播放类的App
在手机端和PC端,页面布局、交互方式都不太一样。
我们现有的跨平台框架最主要的功能就是UI层的复用。
如果UI要有较大差异,那跨平台的优势就会大打折扣。

所以跨平台框架最有优势的场景就是单类平台的多端开发。
比如我们的产品只有Android和iOS端,目前使用Flutter开发。
大多数的UI和业务逻辑代码只需要写一套。
少数情况比如Android和iOS的行为有差异,则在Dart代码中判断不同平台然后分别处理。

但是实际生活中我们用到的很多App还是同时有手机、pad和pc端或者手机、pad和web端的。
Flutter针对这种场景就无用武之地了吗?
其实不是的,这种场景使用Flutter开发也非常适合,只不过需要亿点点策略。

Flutter开发手机、pad和pc端App的策略

这个策略其实也很好理解,就是更精细化的架构分层。
我们先来看一下一个常见App的架构:
image.png

不管使用哪种分层设计策略,一般来说从宏观上大致可以分为三层。
如果你在么一层中的各个功能模块划分是比较清晰的话,那么可以发现:
1、对于下面两层来说,即使在不同类型的平台比如手机端和pc端,它们都用到的模块功能大概率是一致的。
比如逻辑层中的购物车模块。如果手机端和pc端都存在购物车模块,那么这两个端上购物车模块的逻辑功能是一样的。
比如大家都是添加、删除、批量管理、批量结算等操作。
2、对于UI层,相同模块的功能是不一样的。
比如还是购物车,手机端的购物车页面和pc端的购物车页面从布局到交互可能都不一样。

那么,基于上面的特点,我们在使用Flutter开发这种App时,就有了可以遵循的策略。
1、对于业务逻辑层和数据层,可以一套代码多端复用。

对于不包含UI的部分,需要拆分成多个独立的功能模块。
可以把这些模块打包在一个工程中统一进行代码管理。
也可以根据会在哪些端上用到以及迭代速度不同,拆分成2~4个工程,分别进行管理。
不同端上的App可以引用不同的模块。
但是要注意,同一个模块大部分代码应该是不区分平台的。
如果一个模块中有很多判断平台的代码,那应该就要去考虑拆分不同的模块了,甚至有可能一开始模块划分的维度就不合理。

2、对于UI层,需要区分不同的平台。

UI层划分平台,并不是说每个平台单独写一套代码,完全不复用。
而是UI层的代码复用的方式不一样。
我举个例子,微信在手机端和pc端的页面布局是不一样的。
image.png
image.png

但是仔细观察会发现,手机端和pc端会话列表部分的布局是一样的,顶多是替换了一个背景色。
那我们就可以开发一个会话列表组件。
在手机端把这个组件放到回话列表页面里。
在PC端,就放在主页面的左侧。
而不管是手机端还是pc端这个组件请求的接口和返回的数据结构都是一致的。

所以从上面的例子可以看出在UI层,我们复用的是组件而不是整个模块。
而在各种各样的App中也能大量看到这样的场景,就是虽然不同端上的页面布局不一致,但是里面的大块元素其实是一样的。
当然也一定会有一些元素或者组件,只在某一个端上使用。
这种情况就把这些组件放到独属于这个端的工程中就好。

这里插一个题外话,这个例子也能说明另外一个问题,就是为啥Flutter中会把padding之类的功能做成独立组件而不是每个组件的属性。
如果我们开发了一个回话列表组件,在手机和pc端复用。
因为手机和pc上这个组件的大小和位置都不一样。
我们这个会话组件本身不需要关心自己是在哪个端运行,自身的位置和大小都可以由不同端上提供的外部布局组件决定。
这样设计不同代码的耦合程度是极低的。
但是如果这些功能都是通过组件的属性来实现的,那就需要给回话组件设计多个构造参数,用于传入位置、边距、缩进等信息。

总结

前面我们介绍了如何利用Flutter开发跨不同类型平台的实现方案。
当只需要跨同类终端时,比如Android和iOS,就可以通过一个Flutter工程搞定。
如果需要跨越不同类型终端,比如手机和pc端,主要就是要通过多个工程,管理不同层级代码的不同复用方式。
那么回到我们最初的问题。Flutter一套代码跨越6个终端确实是可行的,也有其在实战中的意义。
只不过当面临不同的覆盖范围时需要选择不同的实战方案。

好了,如果看到这里的同学有学习Flutter的兴趣,欢迎联系老刘,我们互相学习。
点击免费领老刘整理的《Flutter开发手册》,覆盖90%应用开发场景。
可以作为Flutter学习的知识地图。
覆盖90%开发场景的《Flutter开发手册》


程序员老刘
1 声望2 粉丝

客户端架构师,客户端团队负责人。一个月带领客户端团队从0基础迁移到Flutter 。目前团队已使用Flutter五年。