首页 > 编程笔记

Flutter是什么?

现在,主流的移动开发平台是 Android 和 iOS,每个平台上的开发技术不太一样,针对每个平台开发应用需要特定的人员,但这样一来开发效率会变得低下,因而需要进行跨平台开发。

移动端跨平台开发技术

跨平台技术从最开始的 Hybrid 混合开发技术,到 React Native 的桥接技术,再到 Flutter 的自建 UI,一直在演进。

Hybrid 开发主要依赖于 WebView,但 WebView 是一个重量级的控件,很容易产生内存问题,而且复杂的 UI 在 WebView 上显示的性能不好。

React Native 技术抛开了 WebView,利用 JavaScript Core 来做桥接,将 JavaScript 调用转为 Native 调用。React Native 最终会生成对应的自定义原生控件。这种策略将框架本身和 App 开发者捆绑在系统的控件上,不仅框架本身需要处理大量平台相关的逻辑,随着系统版本变化和 API 的变化,开发者可能也需要处理不同平台间的差异,甚至有些特性只能在部分平台上实现,这使得跨平台特性大打折扣。

Flutter 是最新的跨平台开发技术,可以横跨 Android、iOS、MacOS、Windows、Linux 等多个系统,还可以打包成 Web 程序运行在浏览器上。Flutter 采用了更为彻底的跨平台方案,即自己实现了一套 UI 框架,然后直接在 GPU 上渲染 UI 页面。

笔者最早接触的跨平台技术是 Adobe Air,写一套 Action Script 代码可以运行在 PC、Android 及 iOS 三大平台上。

笔者与朋友开发视频会议产品,需要最大化地减少前端的开发及维护工作量,所以,我们先后考察过 Cordova、React Native 及 Flutter 等技术。最终经过全面的对比分析,我们觉得 Flutter 方案更加先进,效率更高。

Flutter 是什么?

Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。Flutter 可以与现有的代码一起工作。

在全世界,Flutter 正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

Flutter的特点如下所示:

1) 跨平台

现在 Flutter 至少可以跨 5 种平台,甚至支持嵌入式开发。我们常用的如 MacOS、Windows、Linux、Android、iOS,甚至可以在谷歌最新的操作系统 Fuchsia 上运行。

到目前为止,Flutter 算是支持平台最多的框架了,良好的跨平台性直接带来的好处就是减少开发成本。

2) 丝滑般的体验

使用 Flutter 内置的 Material Design 和 Cupertino 风格组件、丰富的 motion API、平滑而自然的滑动效果和平台感知,为用户带来全新体验。

3) 响应式框架

使用 Flutter 的响应式框架和一系列基础组件,可以轻松构建用户界面。使用功能强大且灵活的 API(针对 2D、动画、手势、效果等)能解决艰难的 UI 挑战。

4) 支持插件

通过 Flutter 的插件可以访问平台本地 API,如相机、蓝牙、WiFi 等。可借助现有的 Java、Swift、Objective-C、C++ 代码实现对原生系统的调用。

5) 60fps超高性能

Flutter 采用 GPU 渲染技术,所以性能极高。用 Flutter 编写的应用可以达到 60fps(每秒传输帧数),这意味着它完全可以胜任游戏的制作。

官方宣称用 Flutter 开发的应用的性能甚至会超过原生应用。

Flutter 的核心概念

Flutter 包括一个现代的响应式框架、一个 2D 渲染引擎、各种组件和开发工具。这些组件有助于快速地设计、构建、测试和调试应用程序。

Flutter 的核心概念有:组件、构建、状态、框架等,下面分别介绍。

Flutter 中一切皆为组件

组件(Widget)是 Flutter 应用程序用户界面的基本构建块。不仅按钮、输入框、卡片、列表这些内容可作为 Widget,甚至布局方式、动画处理都可视为 Widget,所以 Flutter 具有一致的统一对象模型:Widget。

Widget可以定义为:
Widget 具有丰富的属性及方法,通过属性可改变组件的状态(颜色、大小等)及回调方法的处理(单击事件回调、手势事件回调等),方法主要是提供一些组件的功能扩展。比如 TextBox 是一个矩形的文本组件,其属性及方法如下:

Flutter 组件嵌套

复杂的功能界面通常都是由一个一个功能简单的组件组装完成的。有的组件负责布局,有的负责定位,有的负责调整大小,有的负责渐变处理,等等。这种嵌套组合的方式带来的最大好处就是解耦。

例如,界面中添加了一个居中组件 Center,居中组件里嵌套了一个容器组件 Container,容器组件里嵌套了一个文本组件 Text 和一个装饰器 BoxDecoration。

演示代码如下所示:
return Center(
    // 添加容器
    child: Container(
        // 添加装饰器
        decoration: BoxDecoration( ),
        child: Text(
            // 添加文本组件
        ),
    ),
),
大家如果是首次看到这段代码,会觉得嵌套层次太多、太复杂。其实不然,随着对组件的深入了解及熟练使用,写起来还是非常得心应手的。

最基础的组件类是 Widget,其他所有的组件都是继承 Widget 的,如下图所示。紧接着下面有两大类组件:有状态组件及无状态组件。有状态组件是界面会发生变化的组件,如 Scrollable、Animatable 等,无状态的组件即界面不发生变化的组件,如 Text、AssetImage 等。

Flutter组件的层次结构

Flutter 构建

可以通过重写 Widget 的 build 方法来构建一个组件,如下代码所示:

@protected Widget build(BuildContext context);

构建即为创建一个 Widget,返回值也是一个 Widget 对象,不管返回的是单个组件还是返回通过嵌套的方式组合的组件,都是 Widget 的实例。

在 build 方法里我们发现传入了一个参数 context。BuildContext 即构建 Widget 上下文,每一个 BuildContext 对应一个 Widget。在任意一个组件的 build 方法中都需要传入一个 BuildContext 对象。

BuildContext 的作用主要是通过上下文获取指定的数据,如下所示:

Flutter 处理用户交互

如果 Widget 需要根据用户交互或其他因素进行更改,则该 Widget 是有状态的。例如,如果一个 Widget 的计数器在用户点击一个按钮时递增,那么该计数器的值就是该 Widget 的状态。当该值发生变化时,需要重新构建 Widget 以更新 UI。

这些 Widget 将继承 StatefulWidget(而不是 State),并将它们的可变状态存储在 State 的子类中,如下图所示。

有状态Flutter Widget继承示意图

每当改变一个 State 对象时(例如增加计数器),必须调用 setState() 来通知框架,框架会再次调用 State 的构建方法来更新用户界面。

有了独立的状态和 Widget 对象,其他 Widget 可以以同样的方式处理无状态和有状态的 Widget,而不必担心丢失状态。父 Widget 可以自由地创造子 Widget 的新实例且不会失去子 Widget 的状态,而不是通过持有子 Widget 来维持其状态。框架在适当的时候完成查找和重用现有状态对象的所有工作。

Flutter 状态

Flutter 中的状态(State)和 React 中的状态概念一致。State 是一个组件的 UI 数据模型,是组件渲染时的数据依据。

Flutter 程序的运行可以认为是一个巨大的状态机,用户的操作、请求 API 和系统事件的触发都是触发点,触发点通过调用 setState 方法推动状态机进行响应,实现不同的状态,然后渲染 UI,让 UI 与数据保持一致。

状态的生命周期如下图所示。

Flutter状态的生命周期

状态的生命周期每步的作用如下所示:
状态 说明
StatefulWidget.createState Framework 会通过调用 StatefulWidget.createState 来创建一个 State。
initState 新创建的 State 会和一个 BuildContext 产生关联,此时认为 State 已经被安装好了,initState 函数将会被调用。通常,我们可以重写这个函数,进行初始化操作。
didChangeDependencies 在 initState 调用结束后,这个函数会被调用。事实上,当 State 对象的依赖关系发生变化时,这个函数总会被 Framework 调用。
build 经过以上步骤,系统认为一个 State 已经准备好了,就会调用 build 来构建视图。我们需要在这个函数中返回一个 Widget。
deactivate 当 State 被暂时从视图树中移除时,会调用这个函数。页面切换时,也会调用它,因为此时 State 在视图树中的位置发生了变化,需要先暂时移除后添加。
dispose 当 State 被永久地从视图树中移除时,Framework 会调用该函数。在销毁前触发,我们可以在这里进行最终的资源释放。在调用这个函数之前,总会先调用 deactivate 函数。
didUpdateWidget 当 Widget 的配置发生变化时,会调用这个函数。比如,热重载的时候就会调用这个函数。调用这个函数后,会调用 build 函数。
setState 当需要更新 State 的视图时,需要手动调用这个函数,它会触发 build 函数。

Flutter 分层的框架

Flutter 框架是一个分层的结构,每一层都建立在前一层之上。下图显示了 Flutter 框架,上层比下层的使用频率更高。

Flutter框架的分层结构

提示:有关构成 Flutter 分层框架的完整库,请参阅官方的 API 文档,网址为:https://docs.flutter.io/

分层设计的目标是帮助开发者用更少的代码做更多的事情。例如,Material 层通常组合来自 Widget 层的基本 Widget,而 Widget 层通过对象渲染层来构建。

分层结构为构建应用程序提供了许多选项。开发者可以用一种自定义的方法来释放框架的全部表现力,或使用构件层中的构建块,或混合搭配。可以使用 Flutter 提供的所有 Widget,也可以使用 Flutter 团队定制的 Widget。

也就是说,你可以从高层次、统一的 Widget 概念中获得开发效率的优势,也可以深入下层施展你的才能。

所有教程

优秀文章