Flutter无法解决跨平台应用程序面临的最大挑战
从将本地iOS应用程序迁移到Flutter中学到的严厉教训
我对移动应用程序开发的首次尝试始于大约十年前。我刚刚购买了第一台iPhone(3GS),但我很想为这个迷人的小设备创建应用程序。我当时想开发的应用基本上是(现在仍然是)关于类固醇的电子书。它具有大约50章的信息内容,旨在在某些紧急情况下帮助其听众。因此,该应用程序的主要目标是以一种能够在压力很大的情况下使用户快速可靠地找到所需内容的方式来呈现其内容。
最初,我是使用包裹在iOS上的本机PhoneGap容器中的jQTouch库作为Web应用程序启动该项目的。在发布后的一周内,该应用程序就进入了苹果在医疗类别中推荐的应用程序列表,因此看起来该应用程序确实让人感到不安。四年后,在决定在2021年9月将其移植到Flutter之前,我将该应用程序重写为Swift中的本机应用程序。这是我在旅程的最后一步中学到的知识。
Flutter:跨平台应用程序的圣杯?
在决定最终创建该应用程序的Android版本时,显而易见的问题是如何进行。本机Android端口?跨平台?使用Ionic和React还是Vue.js?还是新的酷小子Flutter?在对多平台应用程序开发的当前状态进行了一些研究之后,似乎对后者有了很多炒作。从Medium算法建议的文章中,我得到的印象是,人们通常对Google的项目感到非常满意,而Flutter似乎已经足够成熟,可以作为一种严肃的选择。所以我决定放手一搏。
出乎意料的是,我的最初经验与文章中提到的一样好。信不信由你,但没有Dart和Flutter的UI设计原则的任何先验知识(来自iOS Swift和Xcode Interface Designer),我在一周内就将我的应用程序安装在Flutter上并在Android和iOS上运行-差不多了。
当进行测试时,我开始随机观察到一些非常奇怪的行为:在应用程序中,当电子书的一章正在加载时,我显示了一个微调器。将其加载并呈现在WebView中后,我将旋转器替换为呈现的内容。实际上很简单。这在99%的时间中都有效,但是在随机时间,应用程序会卡在微调器上-对于在紧急情况下应为您提供帮助的应用程序显然是行不通的。如果用户短暂切换到另一个应用程序然后又回到我的应用程序,则花了大约一两天的时间才发现这是由Flutter的HttpServer导致的,该服务器在iOS上崩溃了。笨蛋我提交了一份详尽的错误报告-但很快就找不到解决方法。
由于无法在那种状态下发布我的应用程序,因此我开始寻找替代方法。我决定不通过HttpServer提供我的电子书内容,而是决定将内容从应用程序捆绑包复制到第一个应用程序启动时的应用程序文档目录中,然后使用file://模式直接在WebView中打开HTML。经过一些测试和重构后,这似乎是一个可行的解决方法-直到电子书中的某些链接停止在实际的iOS设备上工作。奇怪的是,Android甚至iOS模拟器中的所有功能都运行良好。原来,我这次在Flutter WebView软件包中发现了另一个我提交的错误,该错误也很快被团队确认,复制和分类。但是直到今天(2021年2月),这两个bug仍然存在于Flutter中。
当我解决最后一个错误时,我花了很多时间来寻找和报告Flutter中的错误,这与我学习Dart和移植应用程序所花费的时间相同。
依赖地狱
浮动httpserver和webview是我应用的两个最重要的依赖关系。没有一个或另一个,我的应用程序将根本无法在该环境中工作。从我的iOS和Cocoapods的经历,这几天我看一下作为技术债务的每一个依赖性:你借用某人的代码或功能,有一天你可能需要支付这一点。
非您自己的代码以及您的应用程序所依赖的任何代码段都会增加应用程序的技术负担。
我个人认为WebView和HttpServer是Flutter技术堆栈的核心部分,因为它们都是由Flutter团队直接开发和支持的,而不是由第三方提供的。(当我尝试使用第三方WebView for Flutter作为替代方法时,我将为您保留一些令人毛骨悚然的细节。)
因此,令我惊讶的是,他们似乎没有受到Flutter团队的热爱。我猜想,要么是Google目前的团队规模不足以开展Flutter之类的项目(到今天为止,已有8230个未解决的问题),要么他们的工作重点放在其他地方。但这确实鼓舞了我对Flutter应用程序的依赖项进行总体考察,并将其与应用程序的本机Swift版本进行比较。要点如下:
原生iOS(Swift)AEXMLFontAwesome.swift
由于本机iOS SDK不提供DOM解析器,因此需要AEXML来解析一些XHTML文件。第二个库使我可以在应用程序中使用流行的FontAwesome图标。
Fluttercupertino_iconsHTTPprovidershared_preferencesfont_awesome_flutterxml2jsonpathpath_providermimeflutter_web_browserwebview_flutterurl_launchergeolocatorgeocodingmap_launcherwakelockdevice_infopackage_infoscrollable_positioned_listin_app_reviewshare
我的天啊!在Flutter中,我需要那么多的包装?好吧,作为一个应用程序而不是一本电子书,我为我的本机应用程序添加了一些其他功能和服务:使用第三方API在线搜索该地区的专业人员,并使用地理位置和反向功能显示有关用户当前位置的信息进行地理编码以帮助指导紧急服务,并快速拨打紧急电话号码。每个功能都需要本机平台SDK中的某些特定功能-例如地理定位,地理编码,触发呼叫或在打开应用程序时阻止睡眠模式。最重要的是,您拥有在任何不错的应用程序中都能找到的基本功能:有时要求用户进行评论,允许与其他应用程序共享内容,启动URL,在特定位置打开地图应用程序或访问某些有关本地设备和操作系统的信息。
尽管iOS和Android开箱即用地在其本机SDK中提供了大多数这些功能,但跨平台解决方案必须为其中的每一个提供一个桥梁,软件包或插件。对于Flutter,它们必须分别以三种语言实现:Dart,Swift / Objective-C和Java / Kotlin。
您的Flutter应用程序将依赖于无数个外部库,以使您能够提供与本机应用程序相同的功能。因此,您的应用程序的功能取决于许多未知的参与者,这些参与者具有不同的议程,时间限制和发展动机。您使用的每个插件都会增加您应用程序的技术负担。
跨平台增加了复杂性
如果您希望减少技术负担,则必须自己编写100%的应用程序代码,并且仅使用本机SDK来提供对底层硬件的访问。每个第三方库都会增加您的技术负担,因此,如果您不能自己实现功能,至少要谨慎选择。
当我开始测试本机iOS应用程序时,最初发现了巨大的内存泄漏。那是从哪里来的呢?了解了梦幻般的保留周期的概念以及如何找到它们之后,我终于找到了罪魁祸首:第三方XML库在递归中泄漏。当我经常用它解析XHTML时,我的应用就变成了记忆猪。
幸运的是,我可以使用自己的Swift技能在库中找到错误,在一天之内修复它,甚至将补丁提交给存储库的所有者。但是我只能找到并修复它,因为库和我的应用程序是用相同的语言编写的,而这是我所熟悉的一种语言。
因此,如果第三方库是开源的,并且使用与您的应用程序相同的语言编写,那么您也许可以很好地承受这种债务。但是每种跨平台解决方案都会为您的应用程序增加多层复杂性,并在每一层上引入更多的故障点。
任何Flutter软件包都可能在其Dart代码,Swift / Objective-C代码或Java / Kotlin代码中失败。Flutter,Dart,iOS或Android的任何更新都可能破坏该软件包的一部分,并使其与您的应用程序在一个或所有平台上兼容。
除非您精通所有三种语言并精通所有受支持的平台,否则您可能无法或不希望找到并解决这些问题。
注意:在撰写本文时,我收到了在装有iOS 12.4的iPhone 6上运行我的应用程序的用户的第二个支持请求。他们报告章节未在其设备上加载。在具有相同硬件/操作系统组合的iOS模拟器中,一切正常。认真地说:如果我没有旧的iPhone 6,应该如何调试呢?即使我设法在Flutter WebView插件的iOS部分中找到该错误,我也不精通Objective-C,也不想花更多的时间来尝试修复IMHO应该可以正常工作的东西,或者声明仍处于alpha或beta状态!
您想依靠谁?
如果项目背后有一个强大的组织来负责为所有主要的本地SDK函数提供到Dart的桥梁,那么Flutter软件包所增加的复杂性就不会那么严重。但是,这一关键部分中的大多数都没有包含在Flutter核心项目中,而是由志愿者来处理。他们的承诺和工作质量从出色的工作到0.1版本后的失去兴趣,不一而足。如果您依靠专业人士提供的包裹,对您有好处。如果您依赖后者,则必须偿还债务。
Flutter真正想要的只是用Dart编写应用程序并将其部署在iOS和Android上。您已经被认为可以使用这种跨平台解决方案,与其他方法相比,可以节省时间和金钱。从理论上讲,Flutter(和其他跨平台解决方案)可以做到这一点。或与Gartner交谈:Flutter的愿景对我来说似乎比较完整(尽管Dart距离Swift尚有很长的路要走)。
但是Flutter的执行能力仍然有很多不足之处,尤其是在iOS上。这是由于偏爱Android吗?还是他们只是缺乏经验?我不知道。但是我所知道的是,这是Flutter作为跨平台开发环境失败的地方。
如果跨平台解决方案不能在所有受支持的平台上可靠地均等地提供常用应用程序功能,则它会失去其与本机应用程序相比的优势,并且从长远来看将失去开发人员的忠诚度。
从我从外部可以看到的一点来看,我严重怀疑Google是否会成功地使Flutter开发成为与原生开发一样的无缝体验。如果他们确实为此目的,他们将需要在该项目中投入更多的精力和人力。这再次需要大量资金,对该项目的坚定承诺以及对未来的清晰愿景。
也许我只是倒霉,而Flutter世界中仅有的两个错误软件包正是我的主要依赖项。但是在阅读GitHub上的未解决问题时,我以某种方式对此表示怀疑。并查看我的应用程序Flutter端口累积的技术债务,我向所有已经参加Flutter培训的开发人员祈祷,Google会加倍努力,而不是一天失去兴趣并让项目死亡。
我个人很想知道Ionic是否会做得更好。因为至少在纸面上,他们在技术债务方面与Flutter面临非常相似的挑战。但这将意味着再次重写我的应用程序。如果有的话,我会告诉你进展如何。