flutter 从0到1

96
ChaoWang
2018.07.06 22:26 字数 2695

flutter 是什么

flutter是Google基于Dart语言开发的移动应用开发框架,在保持原生性能的条件下实现了跨端编程。

官方定义【 Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。】

为什么学习flutter

体验流畅且统一

由于其统一在打包阶段把flutter引擎打包入,统一使用引擎的Skia直接渲染,因此在排版、图标、滚动、点击等方面实现零差异。

远大前景

google 新一代操作系统 Fuchsia 的 UI开发框架;

品质保证

google亲自操刀Flutter以及Dart,能够不断优化,Dart作为新一代编程语言,可用于web、服务端、移动端、物联网 开发,并且支持转译js,其炙手可热程度可见一斑,而且作为全新的语言,其编程体验也是值得肯定。

生态丰富

flutter 丰富的控件库 以及 插件资源,极大得提高开发效率。

技能准备

Dart

Dart于2013年年底发布1.0版本,Google推出Dart 的目的是在 JavaScript 语言的基础上,改进编程效率和软件执行效率,并减少大型软件的编程复杂性。它确实做到第一点, Dart 编写的程序执行效率比 JavaScript 高出 42%到 130%, 其实这对于想投入Html5 而又憎恶 JavaScript的人来说是个福音。

Flutter

基于Dart的跨平台框架,这里我们所要学习的是Flutter相关Api, Flutter提供了相当丰富的Api,以往我们在 Android/Ios中花大力气写的自定义控件,在Flutter中基本是信手拈来。

Flutter官方网站-------Flutter中文网

Pub仓库

Dart的包管理器,Pub之于Dart 就如 npm 之于 node.js, 需要注意的是dart插件分 FlutterWeb两大类。 搜索插件库

android/ios(可选)

开发者完全可以开发纯Flutter应用。 如果需要Native支持的 Pub上也有大量的插件库资源,
但是对于某些开发者的特殊需求(自己开发插件 or 开发混合App),就需要具备相应前端技能了。

环境工具搭建

环境

官方指导:安装Flutter 整个过程简单来说就是:

  1. git(Window用户需要安装 Git For Window) 克隆一份Flutter代码到本地

  2. 配置环境变量(Flutter的Bin目录)

另外:google还贴心得为中国开发者提供了镜像,你懂的。

有些人可能会疑惑,Flutter基于Dart 就如 Android基于Java , Ios 基于 OC, 为什么没有安装Dart的过程,其实这个过程已经在 1 步骤里了, Flutter会自带最新版本的Dart,目前是2.0,
可在在控制在查看Dart版本 (前提是你已经配置了Dart环境变量,官方教程没有这一步).

image

工具选择

如果你仅仅是想开发纯Flutter应用,使用 VsCode 就足够了,毕竟插件强大,内存占用小。
安装Dart插件

如果您需要自行开发插件 或者 开发混合 App, 那么你需要 AndroidStudio 和 XCode。

测试环境

环境和工具安装完成可以测试Flutter安装情况,在terminal运行 flutter doctor

image

这也仅仅是用于参考,该命令工具有时候也不太准确,自己把握就好,其实什么东西没装自己心里没B+树吗?

工程目录

创建工程

无论你是哪种操作系统,哪种开发工具,都可以使用

flutter create myapp

来生成Flutter工程, myapp 可以是任何你想要的工程名。这是我的工程目录:

image
  1. android

    里面存放android相关, 和普通的Android项目目录别无二致,
    可以进行混合开发,其实也是类似于React Native。

  2. ios

    同理普通的Ios项目目录

  3. lib

    用于存放Dart文件用于Flutter执行, 其中 main.dart是程序入口,原生App壳,如Android 的Activity会加载FlutterView作为ContentView, FlutterView就是Flutter加载main.dart渲染出的视图,它有自己的堆栈管理。

  4. test 测试用文件夹

  5. pubspec.yaml

    Pub所用的配置文件,类似于npm的package.json, 用于Dart的包管理,使用的是 caret 语法,效果图如下:

image

pubspec.yaml 配置文件,当配置更新的时候,可以使用 命令 flutter packages get拉取新的配置

name: 工程名

description: 文件描述

dependencies: Flutter工程依赖的库,这里的库包含Pub仓库、本地Pub插件文件夹、插件的git仓库地址

flutter_test::
sdk: flutter: 这里要引入flutter

cupertino_icons:: ^0.1.2 这里引入ios风格的图标

dev_dependencies: Flutter工程依赖的库, 和 dependencies 不同在于,这个标签下面定义的包只在开发模式生效,类似gradle 3.x 的 debugImplementation

  1. pubspec.lock

    pub自动生成的文件,和 pubspec.yaml 密切相关,用于指定程序包所依赖的每个直接和传递依赖项的具体版本和其他标识信息, pubspec.yaml 只列出直接依赖关系,锁文件会确切得指定程序包所依赖的特定版本的包。

Flutter编写

flutter的UI分层比较讲究,从下到上依次为 Dart:ui -> Render -> Animation -> Paint -> Widget -> MaterialWidget/cupertino
关于UI分层以及每一层的作用本篇不做讨论。

如果你足够无聊或者迫不得已,完全可以基于flutter的UI分层比较讲究,从下到上依次为 Dart:ui层或者Render做开发,不过涉及太过复杂的状态管理渲染之类的工作。

本篇只做Flutter的基础认识。

程序入口

首先我们打开 lib 目录下的 main.dart文件,我们基于 widget层编写(VsCode环境):

image

程序的入口:

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

该入口函数在整个app生命周期只会调用一次。 new MyApp() 会返回一个 Widget 控件用于渲染。 上图代码中返回了一个红色的Contaner容器,效果如下:

image

官方不推荐这么做,不推荐直接把widget层的控件作为根控件,原因有个人认为两点(暂时想到两点):

  • 有为数不少的控件不支持直接放置(比如:Text 、 Icon),必须要 MaterialApp或者WidgetApp作为父节点。
  • 直接放置需要开发者作大量的工作来调整布局、样式 等。

推荐使用 MaterialApp 作为程序根节点,原因如下:

  • 统一规范,MaterialApp 引入了 Material Design,还是相当漂亮的,开发者几乎不需要做额外的布局、样式 编码就能达到产品级视觉效果, 当然可以根据需求进行微调。
  • MaterialApp 提供了大量的美观、功能丰富的控件,放弃MaterialApp等于放弃了一整片森林。

正确的姿势是这样的:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Center(child: Text('我是标题')),
          actions: <Widget>[
            Icon(Icons.flight_takeoff),
          ],
        ),
        drawer: Text(''),
        body: new ListView.builder(
          itemCount: 12,
          itemBuilder: (BuildContext context, int index){
              return ListTile(title: Center(child: Text("我是第${index}个item")),);
          },
        )
      ),

MaterialApp 作为根节点, Scafford 脚手架控件,提供了 Drawer、ToolBar、Body 等等,我们可以看看这 27 行代码能实现什么效果。

image

就酱紫,好好想像Android/Ios 实现这效果需要多少文件 多少 代码吧。

控件类型

我们Flutter编码一般都是在 Widget这一层, 上面谈到 程序的 入口是

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

他的作用是创建整个widget视图,整个生命周期只调用一次,那我们怎么怎么更新页面数据呢,我们是不是得保存 Widget 的引用重新设置相应的属性呢?

答案是

No!

我们看一下Widget的具体实现:

@immutable
abstract class Widget extends DiagnosticableTree {

被加上了 @immutable 注解,这意味着控件不可被修改,只能被重新创建。
而我们平时编写 Flutter 继承的是:

abstract class StatelessWidget extends Widget {
                    &
abstract class StatefulWidget extends Widget {

因此,我们不能对已创建的Widget进行修改,那么我们有两个问题:

  1. 我们应该如何 更新页面数据以及布局 ?
  2. StatelessWidgetStatefulWidget 什么玩意儿,什么区别 ?

我们尝试着同时看这两个问题,StatefulWidget 拥有 StatelessWidget 的所有功能,也就是说 StatelessWidget 是他的子集。 StatefulWidget 多了什么?

/**
 * StatefulWidget
 */
class TestStateFulWidget extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
      return TestStateFulState();
  }
}

/**
 * state
 */
class TestStateFulState extends State<TestStateFulWidget>{
  int _index = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        Padding(padding: const EdgeInsets.only(top: 200.0),),
        Text('Count To $_index', style: TextStyle(fontSize: 50.0, color: Colors.red),),
        Padding(padding: const EdgeInsets.only(top: 60.0),),
        FloatingActionButton(   //这是浮动的按钮,支持点击从而触发 onPressed()
          child: Text('Click'),
          onPressed: () {      //onPressed()方法里面对_index自增,并且调用setState(() {})               
            _index++;
            setState(() {});
          },
        ),
      ],
    );
  }
}

效果图

image

具体效果是点击 Click 浮动按钮, 上方的数字增加 1 ,这就是数据更新。

每个StateFulWidget 维护一个 State 对象,当我们对 相关数据更新后 并且 调用了** setState(() {})** 方法,这样就吧 该 Widget 标记为 dirty ,因此会触发控件的更新、替换、删除 等。

打包 ( 以Android为例 )

debug

Flutter开发过程编译会产生 debugapk 包,查看一下我们打出的 debug 包:
/Users/chao/Public/gsy/build/app/outputs/apk/debug/app-debug.apk 目录
利用 Android Studio 分析

image

居然有 31M 我可什么都没有放啊,大头都在 lib, 这什么鬼, libflutter.so是什么

image

这是Flutter虚拟机器, 官方的定义是:

The Flutter Engine is a portable runtime for hosting Flutter applications.

其实这也是Flutter可以跨平台统一的根本所在。

如果你开发Flutter 你会逐渐意识到,为什么感觉 安装包 卡卡的, 真的有官方宣称的 60 帧吗,或者平均50帧。 debug包所运行的东西太多啦, 主要是为了方便开发者开发, 所以这点不用担心,我们尝试着打包release 包。

release

终端运行:

flutter build apk

同样查看release包:

image

只有不足 9M 了,并且体验发现,release包帧率相当得高,甚至比 native开发同样的页面帧率都要高(仅仅针对示本例而言).

主流跨平台框架

维度 Hybird Weex RN Flutter
开发语言 html5+css3+js vue+js+css3 react+js+css3 Dart
是否摒弃标签语言
动画效果支持 一般
用户体验性 一般 流畅 流畅 流畅
插件丰富程度 丰富 较丰富 较丰富 较丰富
界面开发难易程度 较高 较低 较低
是否支持热更新
是否支持和现有项目集
最低支持Android版本 webview支持情况 4.1+ 4.2+
最低支持IOS版本 webview支持情况 iOS8.0+ iOS8+

以上部分数据仅仅是个人以及部分开发同学观点,勿喷。

总结

总体来说Flutter是一门值得学习的技术,有理由相信 google 的Flutter团队会和Dart团队保持密切的合作,并且Dart 虚拟机会更加高效,更加适合Flutter,这是其他框架所不具备的优势

而且Fuchsia系统也采用Flutter作为界面框架,所以,你懂的,就不说了。

Flutter