对比Android和iOS,Windows版Flutter应用开发体验有待提升

发表时间: 2022-05-30 10:08

作者 | Lew C

译者 | 弯月

出品 | CSDN(ID:CSDNnews)

我个人是Flutters的忠实粉丝。我非常喜欢Flutter,以至于有些项目最初选用了其他编程语言,而且几乎已编写完成,但后来我决定弃用,并改用Flutter重写,因为我相信为了将想法转化为应用程序,使用Flutter是最简单的方法。我曾写过一些关于Flutter的文章,而且还花了大把时间创建有关Flutter的内容。

为此,我投入了大量时间研究Flutter应用。我非常希望Flutter能够在Windows上稳定运行。近几年来,Windows开发一直处于萎靡不振的状态,实际上,几乎没有人制作Windows原生应用程序。大多数应用都是Electron或渐进式Web应用。

根据在Android和iOS上开发Flutter应用的经历来看,我认为Flutter整体都保持了高质量。从UI的布局方式到“本周小工具推荐”的推广视频,Flutter的一切都让我着迷。然而,在2022年初,我尝试了Flutter对Windows的支持,我认为目前该项目还处于实验性阶段,要达到稳定状态还有很长的路要走。

CSDN付费下载自视觉中国

Flutter为了支持Windows,并达到如今的水平已经付出了艰辛的努力。但是,目前的状态仍然非常粗糙,几乎无法正常使用。平心而论,如果只是想创建一个简单的应用,不需要与Windows平台集成,或者有现成的插件,那么完全没问题。如果你只想为朋友或同事创建一个简单的应用,不必关心应用是否会崩溃,那么也不会有任何问题。

但是,既然Flutter已经打上了“稳定版”的标签,它对Windows的支持就应该能达到生产水平,并且能够像其他稳定的、受支持的平台(如Android或iOS)一样轻松使用。

我认为“同等水平的稳定体验”指的是平台能够获得全面的支持,就像iOS和Android一样,而且具有良好的体验。然而,尽管Windows平台的Flutter也是“稳定”的,但体验却完全不同。与Flutters对Android和iOS的支持相比,Flutter对Windows的支持有以下明显的缺陷:

  • 为了创建插件,需要掌握C++。而实际上在Windows上开发应用本来应该使用C#或.NET才对。

  • 如果应用想集成其他原生C++库,则需要掌握C++ 和 CMake。

  • 原生库抛出的异常往往会导致应用在桌面系统上崩溃,但在移动设备上,原生异常似乎不会导致应用直接退出。

  • 缺乏文档陈述基本工作原理,以及CMake的构建过程(CMakeLists.txt中只有非常简单的注释)。

  • Android和iOS版本会针对目标设备生成一个可安装的文件。而Windows的构建只能生成一堆文件,你必须自行打包。

这是因为在iOS上使用Flutter和在Windows上使用(两者都是“稳定”平台)的体验截然不同。根据我的经验,感觉Flutter在移动端“非常稳定”,但在桌面系统上的体验却一言难尽……

下面,我们就来详细讨论其中的一些关键点


使用极其不方便的平台框架

大多数Flutter应用既可以使用基本框架提供的功能,也可以使用插件提供的功能。如果你只想创建一个计算器,则不需要使用任何工具包。但是,如果你想创建一个可切换模式的计算器,并保存用户当前的模式,则需要使用shared_preferences之类的包。

这类的包带有“平台实现”,即指定在相应的底层平台上应该执行何种操作。而“平台通道”则可以将信息从多个平台的Flutter代码传输给这些特定于平台的实现。

有时,现有的插件或包无法满足你的需求,你需要自己动手实现。在Android和iOS上,自己动手实现没有任何问题,而且效果很好。对于iOS,你可以使用Swift或Objective-C;而对于Android,你可以使用Java或Kotlin。你甚至可以利用包来生成一些绑定,并享受额外的类型安全。

CSDN付费下载自视觉中国

对于Android开发,我们自然会选择Java或Kotlin;而对于Windows,我们会选择.NET。理由非常充分,因为该语言能够在易用性和性能之间取得良好的平衡,同时还可以减少开发人员编写应用所花费的时间。

另外,现在已有成千上万(当前约有281,952 个)的NuGet包,它们几乎覆盖了Windows所有的功能和外围设备。在Windows上构建Flutter应用时,了解C#与平台通道的基本知识,可以降低编写特定于平台的代码的难度。

Windows平台上的Flutter应用实际上只是Win32应用。如果想编写特定于平台的代码,你必须使用C++编写代码。然而,使用C++的NuGet包数量非常少。如果你想使用特定于平台的功能,就需要花费大量时间在Windows上用C++重新实现这些功能。


核心问题

假设你想在Windows上编写一个Flutter应用,但你的应用打算利用特定平台特定的功能,可惜没有现成的库可以使用,于是你决定自己写一个。

那么,上哪儿去找相关的文档呢?Flutter网站上有很多Android和iOS相关的文档,所以我们假定照猫画虎也能在Windows上实现。例如,这个网页(https://docs.flutter.dev/development/packages-and-plugins/developing-packages#plugin-platforms)说明了如何利用Kotlin创建Android插件,如何利用Swift创建iOS插件,却没有Windows的相关说明。

经过一番搜索后,我找到了Google Codelab于2022 年 1 月发表的这篇文章
https://codelabs.developers.google.com/codelabs/flutter-github-client?hl=en#5)
,其中说明了创建Windows插件的基本步骤。我可以按照这篇指南的说明,构建插件的基本框架。

下面,我需要实现插件的功能。这个过程非常令人沮丧,而且极易出错,我非常希望能拥有pigeon这类的库,在应用和编写的插件之间生成类型安全的绑定。然而,这个库只支持Android和iOS。

所以,我需要从零开始编写平台通道实现。但是,如果我在原生代码中遇到问题,该怎么办?

关于这个问题,目前仍然是未解之谜。Flutter网站没有提供任何相关的文档,所以你只能自己实验,看看能否找到合适的方法。

如此一来,我们面临的困境就显而易见了,根据我的经验,如果插件抛出原生异常,就会导致桌面系统上的应用崩溃,并且Android Studio会抛出消息“与设备的连接丢失”。在经过一系列故障排除之后,最后发现我需要打开Visual Studio,将调试器附加到进程,然后复现应用程序崩溃。Visual Studio才会捕获崩溃,并显示导致原生崩溃的代码的位置。

这意味着,在调试的过程中,我需要通过Android Studio运行应用程序,然后在崩溃发生之前疯狂地尝试重新连接调试器。你需要安装一个Visual Studio的插件,例如ReAttach,等待进程出现,然后附加到它。然而,这个过程也没有相关的文档说明,即便是这种方法能行得通,也会十分蹩脚,而且恐怕你也不确定自己的做法是否正确。

但在调试器成功地附加到进程之后,我对实际情况就有了一定的了解。接下来,我需要链接原生Windows插件所依赖的另一个库。但是Visual Studio有一个很酷的GUI,所以只需点击鼠标右键就可以添加引用了,是吗?不,并没有那么简单。


你还需要了解CMake

我发现,在Visual Studio中添加插件的引用不会影响底层项目。我尝试了一下,添加引用,然后检查Git中的变更,却发现什么都没有。

我花了大量时间研究这个问题,最后发现Windows上的应用其实是CMake项目。我们在Visual Studio中操作的一切,包括解决方案文件、项目文件,都只不过是CMake的构建产物而已。只要运行flutter build windows,这些文件就会被覆盖。

因此,我不能使用Visual Studio来配置项目、添加引用或做任何事情。我只能研究一下如何通过CMake来完成这些工作。此外,我甚至不能通过 Visual Studio安装NuGet包,我必须搞清楚如何通过CMake安装这些NuGet包。

我不太熟悉CMake,它于22年前问世,看起来非常庞大而复杂。坦白来讲,鉴于C++生态系统的广度与深度,以及由C++工具链构建的设备数量,CMake如今的规模也不足为奇。了解CMake与Flutter Windows项目之间的交互是一项艰巨的任务,但为了保证项目顺利进行,你必须有一定程度的了解。

至于相关文档,非常欠缺,甚至可能压根没有。其实我认为这个任务难度不是特别大。任何发布生产级应用的人都会遇到此类问题。就我而言,我尝试Sentry Native集成到我的Flutter桌面应用中,这样在应用崩溃时,我就会收到一些通知。无论想集成哪个库,都需要弄清楚使用哪个包,然后将什么内容添加到CMakeLists.txt中。

C++是一门难度比Swift或Kotlin更高的语言。然而,现代C++已大幅简化,但你仍然需要跟踪指针和引用,注重性能的应用程序尤其需要注意这些方面,对于桌面应用而言,如果能换取更好的开发环境,那么牺牲一些性能,也是可以接受的。

CSDN付费下载自视觉中国

了解C++和CMake不是一件易事,这个要求无疑会削弱在Windows上构建Flutter应用的吸引力跨平台开发本应该更容易,而且我并不反对学习每个平台的特性,然后部署应用。

但是,当我打开应用的错误日志,然后疯狂地在网上搜索“如何使用CMake连接库”时,就觉得心力憔悴。有人决定在Win32之外构建Windows版的Flutter应用,他们肯定也需要配置CMake,对不对?为什么他们没有写一些文档呢?

除了上述问题之外,还有一些小麻烦,比如pubspec.yaml没有标记成可执行文件,因此部署更新会更加困难。虽然这个问题不难修复,但这意味着你需要自定义更多的构建过程,而且随着Windows版Flutter应用的成熟,你肯定需要回头重新修改这个地方。目前,Windows版的Flutter号称是“稳定的”,但其最基本的开发流程、如何创建插件以及如何调试,几乎没有任何相关的文档。这一点非常奇怪。


未来该何去何从?

我认为Flutter是软件开发中的一个革命性篇章,相信随着时间的推移它将成为首选工具。但是,与开发Android或iOS应用相比,Windows版应用的开发体验相差甚远。

我不后悔尝试开发Windows版的Flutter应用,这是一次很好的学习经历。我花了几天时间寻找如何在不使用CMake的情况下连接库,并尝试使用C++编写我的插件。有一次,我花了三天时间研究集成,但最后还是不得不放弃,用git reset抛弃了全部成果。但我在这个过程中学到了很多宝贵的经验。

我担心人们会以为构建Windows版的Flutter应用与构建移动应用的方法相同,到头来却发现这两种应用的构建截然不同,从而变得怒不可遏。在使用Flutter编写Windows应用时,由于不清楚具体的步骤,有时就会觉得一头雾水。

很久以前,Android版的Flutter应用也号称是“稳定的”,就连iOS版的Flutter也今夕不同往日,这两个平台都得到了极大的改进,如今Windows正处在发展的轨道上。相信随着时间的推移,它也会逐步得到完善。但是,Android版在发布时,也不要求我们使用C++编写插件,我们可以使用Java,这门语言使用起来更加方便。而反观Windows版的Flutter,Win32 和 C++却成了基础,我很难想象如何改进二者,才能让Windows上的体验达到与Android 或iOS相同的水平。

目前,Windows版的Flutter可能确实很稳定,因为核心产品不会发生太多崩溃,或者根本不会崩溃。但它仍有一种“不是亲生”的感觉。编写插件很蹩脚,调试很蹩脚,CMake的使用难度很大,等等。想一想,Windows版的Flutter需要经历多少改进,才能达到与移动版本相同的水平。感觉目前Windows版仍处于不同的阶段,比如“预发布”?

考虑到目前在Flutter 3.0中,Linux和macOS的支持已达到“稳定”,做好了投入生产的准备(尽管也缺乏类似的文档),我们只能希望Flutter的“稳定”不是一个泛泛的标签。

理想情况下,我们希望能有一个Flutter的Windows社区负责人(甚至是桌面系统社区的负责人)记录所有问题,说明CMake的构建过程,以及如何将原生库与Flutter应用链接起来。虽然我们知道Windows版应用的开发难度比移动应用更高,但至少我们能有一些如何将它们组织起来的文档。

我并不是说,你不应该构建Windows版的Flutter应用,只不过我们需要认清现实:Windows上的原生软件环境是一片野草丛生的荒原,只有寥寥几个WPF应用,而UWP应用的数量就更少了,还有一些Electron或混合应用可以满足开发人员的需求。我相信,在未来几年Flutter将成为这一领域内强有力的竞争对手。

不过,就目前而言,虽然我仍然很喜欢Flutter,却不知道如何把这种喜爱之情传达给CMake。

*本文由CSDN翻译,未经授权,禁止转载。

原文链接:https://betterprogramming.pub/flutters-stable-experience-parity-is-becoming-a-problem-931318b4cb7b

成就一亿技术人