观望! Flutter!! 谷哥给安卓开发的福利!!!

2字数 3781阅读 1239

Flutter 是什么?

Flutter 移动应用程序 SDK 是为开发人员提供一种创建快捷、美观的应用程序的新方式,从而摆脱过去那种千篇一律的 app
例如,这位开发者这位,或者这位,或者由第三方编辑的一系列文章和视频

与任何新系统一样,用户想知道 Flutter 有什么与众不同之处
“Flutter 有什么新的或者令人兴奋的东西吗?”
这是一个合理的问题,本文将从技术的角度回答 Flutter 有什么东西让人兴奋,而且给出它为什么让人兴奋的原因

但首先,先讲一小段历史

移动开发的简史

移动开发是一个较新的领域
开发者们开始涉足移动开发时间尚不足十年
所以移动开发的工具仍然在发展当中

OEM SDKs

苹果的 iOS SDKs 发布于 2008 年,谷歌的 Android 软件开发工具包发布于 2009 年
这两种工具包基于不同的编程语言,分别是 Objective-C 和 Java


OEM SDKs

通过这些 SDK,应用可以与系统通信以创建 UI 组件或访问系统相机
这些组件被渲染到手机屏幕,而相应的事件则被传回给组件
这个架构足够简单,但仍然不得不为每个平台开发单独的 App
因为这些系统组件都是不一样的,更不用提开发语言的不同了

WebView

第一个跨平台的框架基于 JavaScript 和 WebView
例如 Titanium一系列相关的框架:PhoneGap, Apache Cordova, Ionic 等
在苹果发布 iOS 之前,他们鼓励第三方开发者为 iPhone 构建网页应用程序
因此使用 Web 技术构建跨平台应用程序是顺理成章的一步

WebView

你的应用程序可以创建 HTML 并将其显示在平台的 WebViews 上
请注意像 JavaScript 这样的语言很难直接与本地代码(例如服务)进行通信
因此他们会通过一个在 JavaScript 代码和原生代码的“桥梁”进行上下文切换
因为平台服务通常不会经常被调用,所以这并不会导致太大的性能问题

响应式视图

ReactJS其他的响应式编程框架已经变得很流行了
主要是因为他们通过使用从响应式编程中借用的编程模式来简化 Web 视图的创建过程
2015 年, React Native 将响应式视图的许多优势带给了移动应用程序

响应式视图

React Native 是非常受欢迎的
但是因为 JavaScript 访问了原生 UI 组件
所以它必须经过这些“桥接器
界面上的 UI 控件通常被频繁地访问,在动画、转化或者用户用手指滑动屏幕上的某些组件时,每秒被访问高达 60 次
因此这很可能会导致性能问题

正如关于 React Native 的一篇文章所说:

JS 代码和原生代码本身都是很快的
瓶颈经常发生在当我们视图从一边转向另一边时
未来构建高质量的应用程序时
我们必须将使用桥接的次数控制到最小

Flutter

和 React Native 一样,Flutter 也提供响应式的视图
Flutter 采用不同的方法避免由 JavaScript 桥接器引起的性能问题
即用名为 Dart 的程序语言来编译
Dart 是用预编译的方式编译多个平台的原生代码
这允许 Flutter 直接与平台通信,而不需要通过执行上下文切换的 JavaScript 桥接器
这就会有个问题,即它是如何实现 UI 组件的?

Widgets (组件)

Widgets 是影响和控制应用程序界面的元素
组件是移动应用中最重要的部分之一
UI 表现如何可以成就或毁掉一款 App

Widgets
  • Widgets 的外观和给人的感觉是至关重要的
    包括各种屏幕的尺寸
    也需要有自然的感觉

  • Widgets 必须快速执行
    创建或扩展 UI 控件
    将其放在屏幕上渲染和流畅动画

Flutter 的系统架构包含大量的 Widgets, 不需要使用原生系统 UI 组件或 DOM WebViews
Flutter 配有丰富的可定制的 Android、iOSMaterial Design 组件

Flutter

Flutter 将 UI 组件和渲染器从原生平台移到应用程序中
因此Dart 程序(绿色)和执行数据编码和解码的原生平台代码(蓝色,适用于 iOS 或 Android)之间仍然有一个接口
这比 JavaScript 桥接器快几个数量级

但将 UI 组件和渲染器移到应用程序中会影响应用程序的大小
Android 上的 Flutter 应用程序的的初始大小约为 6.7M

布局思维改变很大

Flutter 最大的改进之一就是它的布局,布局是基于一组规则(也称约束)来决定 UI 组件的大小和位置

传统上,布局使用大量可以应用于任何 UI 组件的规则
这些规则实现多种布局方法,我们就以众所周知的 CSS 布局为例(尽管 Android 和 iOS 中的布局基本相似)
CSS 具有适用于 HTML 元素(UI 组件)的属性(规则), CSS3 定义了 375 个属性

CSS 包含大量的布局模型,如多种箱模型、浮动元素、表、多列文本、分页媒介等
还有像 flexbox 和 grid 的布局模型在之后也被添加进去,因为开发人员和设计人员需要对布局进行更多地控制,而不得不使用表格和透明图像来获取他们想要的布局
在传统布局中,开发人员无法添加新的布局模型,因此必须将 flexbox 和 grid 添加到 CSS 中并在所有浏览器上实现

传统布局的另一个问题是规则可以相互影响甚至发生冲突,通常有几十种规则元素的规则应用于他们,这使得布局变慢
更糟糕的是,布局性能通常为指数性下降
因此,随着元件数量的增加,布局变慢得更快

Flutter 最开始是 Google Chrome 浏览器小组成员进行的实验项目,我们想看看如果我们忽略了传统的布局模式,是否可以构建更快的渲染器
几周后,我们在性能上取得了显著增长,我们发现:

  • 大多数的布局是相对简单的,例如:滚动页面上的文本,其大小和位置只取决于显示大小的固定矩形,还有一些表格,浮动元素等
  • 大部分布局只作用于 UI 组件树的一部分,并且这子树通常使用一个布局模型,因此这些 UI 组件只需要少量的规则

我们意识到如果完全改变以前的布局模式,布局就可以大大被简化:

  • 每个 UI 组件都将指定自己简单的布局模型,而不是拥有可以应用于任何 UI 组件的一整套布局规则
  • 因为每个 UI 组件都有一个更小的一套布局需要考虑,所以布局可以大量优化
  • 为了进一步简化布局,我们几乎将所有内容都转换为 UI 组件

这里是用 Flutter 代码来创建的一个带有布局的简单 UI 组件

new Center (
    child: new Column(
    children:[
      new Text ('Hello, World!')),
      new Icon (Icons.star, color: Colors.green)
     ]
    )

在这段代码中,所有的组成部分都是一个 UI 组件,包括布局
Center UI 组件将其子组件集中在其母组件内(如屏幕)
Column UI 组件垂直排列其子组件(UI 组件列表)
该列表包含一个Text和一个Icon控件(具有一个颜色属性)

在 Flutter 中,居中显示和 padding 都是 widgets
主题是适用于它们子组件的 UI 控件
甚至应用程序和导航也是 widgets

Flutter 包括很多用于布局的 widgets,不仅仅含有列,还包括行、网格、列表等
Flutter 还有一个独特的布局模型
我们称之为用于滚动的“长条布局模型 (sliver layout model)”

通过使用布局进行滚动,Flutter 可以实现高级滚动,如下所示
您可以(并且应该)自己运行这些应用程序,请参阅本文末尾的参考资料部分


sliver layout model

更多关于响应式视图

现有的响应式 web 视图库都引入了虚拟 DOM,DOM 代表 HTML 的文档对象模型 (Document Object Model)
JavaScript 用 DOM 提供的 API 来操纵表现为一个元素树的 HTML 文档
虚拟 DOM 是使用编程语言中的对象(在这种情况下为 JavaScript)创建的 DOM 的抽象版本

在响应式 Web 视图(由 ReactJS 和其他系统实现)中,虚拟 DOM 是不可变的,每次更改,所有的东西都得重建
系统将虚拟 DOM 与真正的 DOM 进行比较,生成一组最小的更改,然后执行这些更改,以更新真正的 DOM
最后,平台重新绘制真实的 DOM 到画布中

虚拟 DOM

这听起来增加了很多额外的工作,但它是值得的,因为操纵 HTML DOM 是非常耗费系统资源的

React Native 也做类似的工作,但是是在移动应用程序当中进行的
它会操控移动平台上的原生组件而不是 DOM
它构建一个 UI 组件的虚拟树,与原生组件进行比较,并只更新已更改的部件


React Native 虚拟树

请记住,React Native 必须通过桥接器与原生部件进行通信,因此,UI 组件的虚拟树可以帮助保持传递桥的最小值,同时还允许使用原生部件
最后,一旦更新了本机部件,平台就会将它们渲染到画布上

React Native 是移动开发的一大进步,并且是 Flutter 的灵感来源,但 Flutter 更进一步

image

回想一下,在 Flutter 中,UI 组件和渲染器已经从平台中集成到用户的应用程序中
没有系统 UI 组件可以操作,所以原来虚拟控件树的地方现在是真实的控件树
Flutter 渲染 UI 控件树并将其绘制到平台画布上
此外,动画发生在用户空间中,因此应用程序(因此开发人员)可以对其进行更多的控制

Flutter 渲染器本身很有趣:它使用几个内部树结构来渲染只需要在屏幕上更新的 UI 组件
例如,渲染器使用“ 使用合成的结构重绘”(这意味着比使用屏幕上的矩形区域更有效)
不变的 UI 控件,即使是那些已经移动的 UI 控件,仅需在内存中做极其细微的改动,速度当然超级快
这就是为什么 Flutter 的滚动性能如此之高,即使在很复杂的滚动场景中

要进一步了解 Flutter 渲染器,我推荐这个视频
你也可以看看代码,因为Flutter 是开源
当然,您可以自定义或甚至替换整个堆栈,包括渲染器,合成器,动画,手势识别器,当然还有 widgets

Dart 编程语言

因为 Flutter 像使用响应式视图的其他系统一样,刷新每个新框架的视图树,它会创建许多只能在一帧(六十分之一秒)内存在的对象
幸运的是,Dart 使用“generational garbage collection ”对于这样的系统来说是非常有效的,因为对象(特别是寿命短的)消耗资源相对较少
此外,可以使用单个 pointer bump 来完成对象的分配
这有助于避免 UI 卡顿

Dart 还有一个“tree shaking ”编译器,它只包含你在应用程序中需要的代码。
即使您只需要一个或两个,您也可以随意使用大型的 UI 控件库

兼容性

因为 UI 组件是您的应用程序的一部分,而不是平台的一部分,不需要“兼容库
您的应用程序不仅可以正常工作,而且在最新的手机操作系统上表现也是一样的

由于 Flutter 不使用原生 UI 组件
因此,当新的 iOS 或 Android 版本出现时
Flutter UI 组件是否需要更新才能支持新的部件,或更改现有部件的外观或行为吗?

  • Google 是 Flutter 的内部的一个大用户,所以有很大的动机来更新 UI 组件,使其保持最新状态并尽可能接近当前的原生 UI 组件

  • 如果有一段时间 Google 在更新一个 UI 组件时太慢
    Flutter 的 UI 组件是可扩展和可定制的,任何人都可以更新它们
    当然, 自己造轮子需要更多的力气

其他

Dart 拥有一个软件包仓库
您可以用这些软件包扩展应用程序的功能
例如,有许多软件包可以轻松访问Firebase,以便您可以构建“无服务器”应用程序
外部贡献者创建了一个可让您访问 Redux data store的软件包
还有一些称为“plugins ”的软件包,可以以独立于操作系统的方式轻松访问平台服务和硬件,例如加速度计或相机

Flutter 也是一个开放源码的项目
加上 Flutter 渲染堆栈是您应用程序的一部分
这意味着您可以自定义几乎任何您想要的应用程序
该图中绿色的部分您都可以定制:

可定制

那么,Flutter 怎么上手并实际使用呢?

值得肯定的是 Flutter 具有以下优点:

  • 响应式视图的优点,不需要 JavaScript 的桥接器
  • 代码将 AOT 跨平台编译为本机(ARM)代码
  • 配有美观快速且开发者完全可定制的 UI 组件和布局

但也有以下难点:

  • Dart 语言下 UI 布局风格和原生代码相差很大, 需要学习成本
  • 很多地方可能需要自己造轮子, 需要更多力气

综上所述, 本人作为iOS开发者持观望态度
待其发展更高版本再深度接触不迟