前端 Flutter 入门指南

avatar
@北京抖音信息服务有限公司

出品:西瓜视频前端技术团队

作者:@李春霖

一、Flutter 是什么?

Flutter 是 Google 推出的 UI 框架,帮助开发者通过一套代码同时运行在 iOS 和 Android 上,构建媲美原生体验的精美应用!实际上 Flutter 不止于移动平台,正逐渐从移动设备扩展到多个平台,例如 Web、macOS、Windows、Linux、嵌入式设备等,因此 Flutter 是适用于所有屏幕的便携式界面框架,Flutter 一切皆是 Widget;自绘 UI;Flutter 只接管 UI 层,蓝牙等系统功能通过插件的形式提供。

二、Flutter 有哪些特点?

  1. 美观:可对 UI 实现像素级的控制,且内置 UI 库 ( Material、Cupertino )
  2. 快速:硬件加速图形引擎、代码被编译成机器码
  3. 高效:保持应用状态的热重载 ( hot reload )
  4. 开放:完全开源的项目 ( BSD 开源协议 )

三、Flutter 系统架构

Flutter 使用 C、C++、Dart 和 Skia ( 2D 渲染引擎 ) 构建,详情见 Flutter 系统架构

Flutter ( Android / iOS )Flutter Web

四、Flutter 与前端的一些对比

技术都是相通的,寻找相似点能让我们快速上手一门新技术。

Flutter 与前端有不少相似点,比如 Flutter 借鉴了 React 响应式 UI 编程的思想,Flutter 也有 Flexbox、Grid 布局,此外 Dart 与 JavaScript 的语法有不少相似点。

实际上,Flutter 项目正是诞生于 Chrome 团队,详情见 “听 Flutter 创始人 Eric 为你讲述 Flutter 的故事”。此外,Dart 设计之初是为了取代 JavaScript,只不过最终取代失败,因而转换定位,服务于 Flutter。

Flutter前端
编程语言DartJavaScript
响应式 UI 编程借鉴 ReactReact、Vue、Angular
状态管理Provider、Redux、MobxRedux、Mobx、Vuex
页面样式WidgetsCSS、styled-component
UI 库官方内置 Material Design、Cupertino社区 Ant DesignElement
内嵌视图PlatformViewiframe
开发和调试工具Dart DevToolsChrome DevTools
编辑器VS Code、Android StudioVS Code、Sublime Text
在线编辑器DartPadCodePenCodePen、JSFiddle
包管理工具pubnpmyarn
DartJavaScript
编译即时编译 (JIT) 或提前编译 (AOT)即时编译 ( JIT )
异步非阻塞单线程、事件循环、微任务、宏任务单线程、事件循环、微任务、宏任务
异步编程Future、async、awaitPromise、async、await
类型系统type safestatic type checking and runtime checksTypeScriptstatic type definitions
继承Class原型链
密集型计算IsolateWeb Worker
FlutterCSS
样式化文本Text、RichTextfont-size、font-weight、font-family...
盒模型只有 border-boxbox-sizing: content-box、border-box;
弹性盒子布局Row、Columndisplay: flex、inline-flex;flex-direction: row、column;
网格布局Griddisplay: grid;
定位方式Aligin、Stack & Positioned、Sliversposition: static、relative、absolute、sticky、fixed
变换 ( 旋转 缩放 倾斜 平移等 )Transformtransform

举个🌰

<div class="greybox">
    Lorem ipsum
</div>

.greybox {
    background-color: #e0e0e0; /* grey 300 */
    width: 320px;
    height: 240px;
    font: 900 24px Georgia;
    display: flex;
    align-items: center;
    justify-content: center;
}
// Flutter Dart
var container = Container( // grey box
    color: Colors.grey[300],
    width: 320,
    height: 240,
    child: Center(
        child: Text(
            "Lorem ipsum",
            style: TextStyle(
                fontWeight: FontWeight.w900,
                fontSize: 24,
                fontFamily: "Georgia",
            ),
        ),
    ),
 );

五、Flutter 为什么选择 Dart ?

  1. Flutter 选择开发语言时,使用 4 个主要维度进行评估,Dart 在所有评估维度上都取得高分
  • 开发者的生产力
  • 面向对象
  • 稳定可期的高性能表现
  • 快速内存分配
  1. Dart 的运行时和编译器支持 Flutter 的两个关键特性
  • 基于 JIT ( 即时编译 ) 的快速开发周期,允许在带类型的语言中支持形变和有状态热重载
  • 一个能产出高效率 ARM 代码的 AOT (Ahead of time 提前编译) 编译器,从而确保快速启动的能力和可预期的生产版本运行性能
  1. Dart团队就在你身边:与 Dart 社区展开了密切合作,Dart 社区积极投入资源改进 Dart,以便在 Flutter 中更易使用

六、Flutter 性能为何能够媲美原生应用?

FlutterAndroid、iOSHybridReact Native、Weex

七、Flutter 与原生交互

  1. PlatformChannel

适用于不带 UI 的功能,Flutter 与原生约定通道方法,原生通过 API 的形式提供定位、蓝牙、传感器等系统功能,或者复用客户端 SDK,提供请求、上传、美颜、人脸识别、推送、 IM 等基础功能

  1. PlatformView

适用于带 UI 的功能,Flutter 内嵌原生视图,例如地图、WebView 等

Widget build(BuildContext context) {
  if (defaultTargetPlatform == TargetPlatform.android) {
      return AndroidView(
        viewType: 'plugins.flutter.io/google_maps',
        onPlatformViewCreated: onPlatformViewCreated,
        gestureRecognizers: gestureRecognizers,
        creationParams: creationParams,
        creationParamsCodec: const StandardMessageCodec(),
      );
    } else if (defaultTargetPlatform == TargetPlatform.iOS) {
      return UiKitView(
        viewType: 'plugins.flutter.io/google_maps',
        onPlatformViewCreated: onPlatformViewCreated,
        gestureRecognizers: gestureRecognizers,
        creationParams: creationParams,
        creationParamsCodec: const StandardMessageCodec(),
      );
    }
    return Text(
'$defaultTargetPlatform is not yet supported by the maps plugin');
  }
}
  1. Texture

适用于带 UI 的功能,原生提供图像数据 ( 相机拍摄画面、视频播放帧 ),Flutter 通过 ID 引用原生存放于 GPU 的图像数据,然后自定义 UI,例如相机、相册、播放器等

八、Flutter 开发体验:"UI as Code"

Flutter 的 UI 代码使用 Dart 语言,其优点如下:

  • Flutter 的声明式 UI 编写方法能够直观地描述 UI 结构 ( 借鉴 React )
  • 不需要为 UI 布局学习额外的语法
  • 不需要维护代码之外的 UI 定义文件

但是,也存在几个问题:

问题一:复杂 UI 逻辑会使用命令式语法,打破代码结构和 UI 视觉结构的一致性 ( 代码看起来更像是命令式的而不是声明式的 )

image.png

Widget build(BuildContext context) {
  List<SegmentedTabBarItem> items = [];
  List genders = ["男生", "女生", "不限"];
  for (int i = 0; i < genders.length; i++) {
      items.add(SegmentedTabBarItem(
          text: genders[i],
          width: 102,
          radius: 8,
          fontWeight: FontWeight.w500,
          selectedTextColor: Colors.white,
          duration: Duration(milliseconds: 0),
      ));
  }
  return SegmentedTabBar(
      tabItemSpacing: 6.5,
      tabBarRadius: $rem(12),
      tabIndex: genderIndex,
      padding: EdgeInsets.symmetric(horizontal: 0),
      selectedItemBackgroundColor: Colors.purple,
      duration: Duration(milliseconds: 0),
      children: items,
      onSelected: (int index) {
          setState(() {
              genderIndex = index;
          });
      },
  );
}

SegmentedTabBar 在概念和视觉上都应该先于 items 出现。但是由于语法局限,这个空间关系被反了过来。代码看起来更像是命令式而不是声明式。


解决方案:在 Dart 2.3 中加入了针对 UI 编程优化的新语法元素,即可以在集合数据类型的定义中使用 if 和 for 这样的流程控制元素。

Widget build(BuildContext context) {
  return SegmentedTabBar(
      tabItemSpacing: 6.5,
      tabBarRadius: $rem(12),
      tabIndex: genderIndex,
      padding: EdgeInsets.symmetric(horizontal: 0),
      selectedItemBackgroundColor: Colors.purple,
      duration: Duration(milliseconds: 0),
      children: <SegmentedTabBarItem>[
          for (String label in ["男生", "女生", "不限"])
              SegmentedTabBarItem(
                  text: label,
                  width: 102,
                  radius: 8,
                  fontWeight: FontWeight.w500,
                  selectedTextColor: Colors.white,
                  duration: Duration(milliseconds: 0),
              ),
      ],
      onSelected: (int index) {
          setState(() {
              genderIndex = index;
          });
      },
  );
}

问题二:多层嵌套之后不容易对 UI 的构成做到一目了然

解决方案:IDE 中加入了 Editor UI Guides

image.png

九、Flutter 开发调试工具

Demo 演示

参考资料

关于我们

我们来自字节跳动,是旗下西瓜视频前端部门,负责西瓜视频的产品研发工作。

我们致力于分享产品内的业务实践,为业界提供经验价值。包括但不限于营销搭建、互动玩法、工程能力、稳定性、Nodejs、中后台等方向。

欢迎关注我们的公众号:xiguafe,阅读更多精品文章。

我们在招的岗位:job.toutiao.com/s/h2BU5d8 。招聘的城市:北京/上海/厦门。

欢迎大家加入我们,一起做有挑战的事情!

谢谢你的阅读,希望能对你有所帮助,欢迎关注、点赞~