Hello Flutter

Flutter 是 Google 在 2015 年发布的一款跨平台 UI 开发工具包,支持 Android 及 iOS 平台,同样也是 Google Fuchsia 的主力开发工具。
作为 Android 开发有学习 Flutter 的必要吗?个人觉得很有必要,首先这是 Google 在主推的一个项目,并且国内阿里腾讯等等大厂都已经有使用 Flutter 开发的项目了,有他们背书,不用怕有什么填不满的坑。另外,其实作为一个 Android 开发,很容易觉得能力无法更进一步,基本上每个程序员都有这样的经历,觉得自己的能力已经能胜任所有的工作,该会的也都会了,没有办法更进一步突破自己的天花板,换个角度想,或者通过另一个层次来看现在的自己,Android 开发的未来到底在哪,未来的移动端开发到底应该是什么样,原生开发会被抛弃吗?
跨平台一直以来都是大家很关注的话题,很多公司都有一些尝试,而对于 Flutter 来说或许能一统大前端的江湖,如果能做到在不牺牲性能的的情况下做到跨平台,那有谁能拒绝他呢。
混合开发肯定还会继续下去,但原生负责的业务可能会降低,核心功能用原生,页面以及边缘业务使用 Flutter 开发快速迭代,这应该是理想的开发模式。

什么是 Flutter

Flutter 是一个移动端跨平台开发工具包,可以实现一次编写、到处运行,并且性能可以媲美原生。
关于移动端的跨平台开发已经有过很多次尝试,不论是基于 WebView 的 Cordova、VUE,还是可以渲染成原生控件的 React Native 、Weex,性能上总是差强人意,体验也比较差。
而 Flutter 就比较厉害了,另辟蹊径,直接重新写了一套 UI 组件,然后使用 2D 渲染引擎 Skia 将其渲染出来,性能上自然不会太差。所以我们在开发时使用 Flutter 内置的 UI 组件,完成后 Skia 会直接调用系统的图形接口绘制页面,并且 Flutter 使用支持 AOT 的 Dart 语言,性能也要比 JavaScript 高。
Flutter 支持使用 IDEA、AndroidStudio、VS code 开发,只要安装相应的插件即可,另外 Flutter 再调试模式下使用 JIT 方式运行,此时可以使用引以为傲的 Hot Reload 功能,可以实现代码更改后立马看到 APP 上的效果。

Dart

Dart 是由 Google 主导开发,在 2011 年发布的用于 Web 开发的编程语言。
Dart 语法特质类似 C 语言,同样是面向对象的编程语言,具备三种运行方式:

  • 编译成 JavaScript 代码,运行在浏览器中
  • 运行在 DartVM 虚拟机中(JIT,Flutter 调试模式下使用这种方式运行)
  • 编译成机器码直接运行(AOT)

对于有 Java 基础的开发者来说,学习 Dart 成本并不高,简单易上手,所以如果感兴趣的话就赶紧开始吧。

Flutter 的组织形式

上面只是大概的介绍了 Flutter 的一些基本概念,那么 Flutter 到底是如何运行在设备上的呢?以什么样的方式与原有的项目进行结合呢?
我们可以先创建一个简单的 Flutter 项目,然后编译运行,看看这中间到底经历了哪些过程,最终生成的 apk 到底长什么样子。

Flutter apk

我们先创建一个 flutter 项目,然后打包一个 APK 看看到底长什么样子,flutter 项目的 debug 模式和 release 模式下生成的 apk 区别很大,这里先看 release。
下图为一个 flutter 项目 release 模式下的 apk 结构:

默认情况下会生成 arm64-v8a 和 armeabi-v7a 两种 so,我们可以通过配置使其只生成 armeabi-v7a 的 so 文件,这样包体积可以减少至少 5MB 左右。

lib 中有两个 so,libflutter.so 是 flutter 的运行环境,占用 3.2 MB;libapp.so 是我们的 dart 代码编译后生成的代码。
另外,assets 中还有一些 flutter 的一些文件,占了大概 170 KB,所以 flutter 还算是个轻便的框架,总共也就占用了 3MB 多一点的空间。

下面再看看看 debug 模式下的 apk 包结构:

debug 模式下会有很大的不同,首先,lib 中只有一个 libflutter.so,且体积会比较大。
上面已经介绍过了,debug 模式下 dart 运行方式为 JIT,所以 dart 代码并不会被编译成机器码,因此我们会看到 assets 中多出了一些文件,这就是 dart 代码产生的文件。

Flutter Project

一个常规的 flutter 项目树形结构如下:

简单说下,android 文件夹中自然是 android 平台的代码,ios 下是 iOS 平台对应的代码,lib 中是 dart 代码,我们 flutter 项目的 dart 代码主要都在这里面。
主要来看看 android 下面的东西。
android 目录下是一个标准的 Android 项目,其中只有一个自动创建的 MainActivity,代码如下:

class MainActivity: FlutterActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    GeneratedPluginRegistrant.registerWith(this)
  }
}

其中代码很简单,继承自 FlutterActivity,FlutterActivity 中重写了 Activity 的生命周期的几个方法以及一些常用回调方法,然后将其委托给 FlutterActivityDelegate 处理,其中代码大概长这样:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.eventDelegate.onCreate(savedInstanceState);
}

protected void onStart() {
    super.onStart();
    this.eventDelegate.onStart();
}

也就是说 FlutterActivityDelegate 其实是接管了 Activity 中的各种回调事件,显然是提供给底层处理。
那么来看看重点 FlutterActivityDelegate 中的代码。
我其实比较关心的是 setContentView,这个 Activity 到底是个什么鬼,里面装了什么东西。
现在看下 FlutterActivityDelegate 的 onCreate 方法:

public void onCreate(Bundle savedInstanceState) {
    //省略代码
    this.flutterView = this.viewFactory.createFlutterView(this.activity);
    if (this.flutterView == null) {
        FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
        this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
        this.flutterView.setLayoutParams(matchParent);
        this.activity.setContentView(this.flutterView);
        this.launchView = this.createLaunchView();
        if (this.launchView != null) {
            this.addLaunchView();
        }
    }
    //省略代码
}

其实就是创建一个 FlutterView,然后 setContentView 到 Activity 中,也就是说 Activity 是一个包含一个 FlutterView 的页面。
而 FlutterView 继承自 SurfaceView,并且接收 FlutterActivityDelegate 中的生命周期方法回调,再通过 JNI 传到 native 层。
真相大白,Flutter 使用 Skia 把我们的 dart 代码渲染成图形,并使用 SurfaceView 显示出来,同时 Activity 将各种点击事件、方法回调通过 JNI 传给 native 层,完美。
现在我们明白了 Flutter 在手机上的运行机制,也明白了 Flutter 到底是个什么东西。另外还有一点需要注意的,通过查看清单文件发现使用自定义的 Application:FlutterApplication。在 APP 启动时会做一些初始化操作,比如应用各种设置,加载 so,以及提取 dart 代码到私有目录。
我们上面说了 debug 模式下 dart 代码会打包到 assets/flutter_assets 资源文件目录下,在 APP 启动时会将该文件夹下的文件提取到私有目录中。

Hello World

现在开始尝试创建一个 Flutter 项目并运行到手机上。
安装其实比较简单,这里大概说下流程,详细的官网上有:

  • 下载 Flutter SDK 并解压
  • 配置 Flutter 相关的环境变量
  • 安装 Android Studio 的 Flutter 插件

详情见官网,我这里就不倒卖二手资料了:
https://flutter.dev

插件安装好后创建一个 Flutter 项目,项目目录结构上面已经介绍过了,我们直接打开 lib 下的 mian.dart 文件,编辑代码:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text(
          'Hello World!',
          textDirection: TextDirection.ltr,
        ),
      ),
    );
  }
}

上面代码是创建了一个 Material Design 风格的页面,Toolbar 显示 Flutter Demo Home Page,中间有个文本显示:Hello World!
这些还是比较简单的,好了关于 Flutter 的介绍就先到这里,本文章只是大概的介绍了 Flutter 的一些基本概念,后面会有一系列关于 Flutter 的文章,还请大家多多关注。

你可能感兴趣的:(Hello Flutter)