为什么说Flutter让移动开发变得更好?<

时间:2018-07-12 08:51 来源:http://www.searchhyip.com

  在开始之前,先打一个预防针。 这篇文章演示用到的app相对简单,几乎没有业务逻辑。 示例很基础,但这是分享将原生 Android 应用移植到 Flutter 的最好例子。该示例没有任何架构,就是最纯粹的原生调用。

  一年前,我在 Play Store 上架了第一款 Android 应用。 该应用的架构和编码都非常简单 ; 这是我的第一个大型开源项目,这个 app 了我的 Android 学习道。之后在一家代理公司工作,接触到了不同的技术和架构,包括 Kotlin,Dagger,RxJava,MVP,MVVM,VIPER 等,这些对我的 Android 开发确实有帮助。

  然而,在过去的几个月里,很想吐槽一下 Android 开发,特别是关于兼容性。关于每次调试的构建时间更是无力吐槽......Kotlin 和 Databinding 的出现让问题有所改善,但仍然是杯水车薪。 Flutter 可以说出现的很及时。

  几周前我开始使用 Flutter,那时还是 beta 版。通过文档和示例开始了 Flutter 的学习旅程(文档写的特别棒)。 很快,我开始理解 Flutter 背后的设计思想,并决定自己尝试一下,看看能否将 Flutter 投入使用。 一开始我在想用什么项目来练手,考虑后决定移植我的第一款 Android 应用到 Flutter。 这似乎是一个合适的选择,因为它可以让我以入门的姿态比较两种框架的优劣,同时不会过分关注应用程序架构。

  我首先创建了网络请求,解析JSON,并习惯了 Dart 的单线程并发模型(这可单独作为一个主题来讲)。 在接收到网络请求响应后,开始创建列表布局和列表元素。 Flutter 创建布局的只需要扩展各种Widgets并重载几个方法。 接下来我会比较 Flutter 和 Android 在构建这些功能时的差异。 让我们从在 Android 中构建此列表所需的步骤开始:

  当然,这很繁琐。 构建这些功能其实是相当普通的任务,这是一个很寻常的用例, 你可能很想知道:是否有更好的方式来实现? 一种不太容易出错的方式,能否只涉及较少的样板代码,提高开发速度? 下面该 Flutter 入场了。

  Flutter 吸收了移动开发领域多年来在应用程序开发,状态管理,应用程序架构等方面积累的经验,这也是为什么会与 React.js 如此相似的原因。用 Flutter 的方式来构建应用时正确的开始。 下看看如何在 Flutter 中实现的例子:

  为电影项目创建一个无状态的 Widget(无状态,因为包含静态属性),接收一个 movie(例如 Dart 类)作为构造函数参数,并以声明方式描述布局,同时绑定电影的值(名称 ,发布日期等)到 Widget。

  让我们看看这里发生了什么。 最重要的是,我们使用了 FutureBuilder(Flutter SDK 的一部分),它需要我们指定一个 Future(回调)和一个构建器函数。 构建器函数为我们提供了一个 BuildContext 和要返回的项目的索引。 使用这个,我们可以检索一个电影,给定 Future 的结果列表,快照,并创建一个 MovieListItem-Widget(在步骤 1 中创建),并将该电影作为构造函数参数。

  然后,当第一次调用构建方法时,开始等待 Future 回调的返回结果。 一旦得到返回结果,构建器会再次被调用,我们可以用返回结果来构建我们的 UI。

  这貌似太简单了...... 现在有没有感觉到用 Flutter 创建列表很容易,继续探索吧。

  下一步我们尝试稍微复杂的布局。 该应用的电影详情有相当复杂的布局,包括约束布局和应用程序栏。 这样的布局展示能获得用户的青睐,如果 Flutter 想要在 Android 里有立足之地,那么需要能够提供更复杂的布局方式。 下面看看我是如何构建的:

  该布局由 SliverAppBar 组成,其中包含电影图像的堆叠布局,渐变,气泡和文本图层。 能够以模块化的方式表达布局使得创建这种相当复杂的布局变得非常简单。 下面是实现:

  在构建布局时,我将布局的各个部分模块化为变量,方法或其他小部件。 例如,图像顶部的文字气泡只是另一个小部件,它将文本和背景颜色作为参数。 创建一个自定义视图就像这样简单:

  想象一下,在 Android 中构建一个像这样的自定义视图有多困难。不过,在 Flutter,这分分钟解决。能够将用户界面的一部分抽取到像 Widget 这样的自包含单元中,可以轻松地在应用程序中甚至跨不同应用程序重复使用这些小部件。这个应用中,布局的很多部分都在不同界面上重复使用,并让我告诉你:这真的很简单。前面太容易了,我决定扩展应用程序,合并电视节目。

  几个小时后也顺利完成了。该应用程序包含了电影和电视节目,并且开发过程中没有遇到任何困难。我通过构建用于加载和显示数据的泛型类来实现,这使得我可以重复使用电影和演出的每个布局。如果用 Android 实现相同的事情,我必须为电影和演出分别使用不同的 Activity。可以想象这让工作瞬间变得复杂,并且 Android 对于布局的共享处理方式不太灵活。

  现在不用再像 Fragment 一样去管理状态,这很繁琐也很容易出错。 不用再为一点点修改而重新构建应用,浪费时间。 不再有 XML 布局, 也不再有 findViewById。 不再有多余的样板代码 。

  既然两个 app 的功能几乎一样,我就比较好奇两种不同语言实现的代码量。 那么应该如何进行对比?(免责声明:Flutter 版本中还没有实现持久化,原生代码写的也很乱)。 我们使用 Cloc 来进行代码的比较,为了简单起见,我们来看 Android 上的 Java 和 XML 文件,以及 Flutter 版本的 Dart 文件。

  我期待的 Flutter 版本可能只有原生 Android 的一半代码量,但实际减少了 85%的代码量?完全超出预期。 但仔细想想又在意料之中:因为所有的布局,背景,图标等都需要用 XML 来指定,并且仍然需要使用 Java / Kotlin 代码连接到应用程序, 这里产生了大量的代码。

  使用 Flutter 可以一次性完成的步骤并把值绑定到 UI 上。 现在无需处理 Android 中的数据绑定,比如设置或处理生成的绑定代码。 在 Android 上构建这些基本的东西非常繁琐。 为什么要一次又一次地为 Fragment / Activity 参数,适配器,状态管理和恢复等类似的代码编写相同的代码?

  当然,这仅仅是 Flutter 的开始,因为它仍处于测试阶段,远没有 Android 成熟。 不过,相比之下,Android 似乎已经达到了极限,很快就可以使用 Flutter 中编写 Android 应用程序了。 还有一些事情需要解决,但总的来说,Flutter 的未来看起来很。目前 Android,VS Code 和 IntelliJ 都已经拥有支持 Flutter 的插件,并且还会有更多的工具会陆续产生。 这一切都让我相信,Flutter 不仅仅是另一个跨平台框架,而是更大的开始 - 应用程序开发新时代的开始。

  当然,你可能会问自己:我现在必须学习一个完整的其他框架吗?刚学习了 Kotlin 并使用架构组件,现在一切都很好。为什么我们想要去了解 Flutter?但让我告诉你一点:在使用 Flutter 之后,你将开始理解目前 Android 开发存在的问题,并且很明显 Flutter 的设计更适合现代的,响应式的应用程序。

  当开始使用 Android 的 Databinding 时,我认为这是性的,但它也感觉像是一个不完整的产品。使用 Databinding 处理布尔表达式,和更复杂的布局相当繁琐,这让我意识到 Android 并不是为这样的工具设计的。Flutter 使用 Databinding 相同的思想,即将视图 / 小部件绑定到变量,而无需在 Java / Kotlin 中手动管理数据绑定,不用专门的绑定文件来桥接 XML 和 Java。这可以将以前至少有一个 XML 和Java文件的内容压缩到一个可重用的 Dart 类中。

  我也可以说 Android 上的布局文件本身并不做任何事情。 他们必须先布局,然后才可以设置值。 这也引出了状态管理问题,并提出了一个问题:当绑定的数据发生了变化应该怎么处理? 手动获取相应视图的引用并设置新值? 这种方法真的很容易出错,这样管理 View 的状态很差劲。 相反,我们应该使用状态来描述布局,每当状态发生变化时,框架会重新渲染视图。 这样,我们的应用程序状态就不会与 Views 显示的内容不同步。 而 Flutter 正是这样做的!

  还有另外一个问题:你有没有问过为什么在Android上创建工具栏菜单非常复杂? 我们为什么要用 XML 来描述菜单项,这无法将任何业务逻辑绑定到 XML(这是菜单的全部目的),然后在Activity/Fragment的回调中进行过设置,然后再绑定真实回调到另一个回调上? 为什么不可以一次性设置好,就像Flutter一样?

  正如代码所示,我们将菜单项添加为AppBar 的 Actions。 这就是全部 - 不需要再将图标导入成 XML 文件,不再需要重写回调。 只需要在 Widget 上加一些小的Widgets就可以了。