Flutter实战总结

先放一下Flutter的练手Demo

代码仓库地址 https://github.com/kunkun12/Flutter_shop

2014年谷歌开始搞了个实验项目 Sky ,在Dart Developer Summit 2015 第一次亮相Sky: An Experiment Writing Dart for Mobile (Dart Developer Summit 2015),号称基于Dart来开发现代化移动优先的高性能 跨平台App、帧率可以达到120fps及以上,2015年10月 Sky 改名为Flutter,并发布了官方网站Flutter.io,谷歌内部开始用Flutter开发实际项目,2018年发展迅速,开始火起来了,2018年12月初Flutter 1.0 released。可以看出Flutter跟RN差不多是同时期的产品,Flutter在应用层玩法也是受React很多的启发,二者UI绘制工作原理不同,RN用的系统SDK的UI,Flutter是自绘制的UI,操作UI不需要bridge来进行通信 因此确保了性能,Flutter团队的成员大都是来自Chrome团队,里面也融入了不少Web的思想,以及Flutter的技术负责人也是因此Flutter玩法对web开发者比较友好 。更多Flutter原理 如何评价 Google 的 Fuchsia、Android、iOS 跨平台应用框架 Flutter

Flutter早起成员之一Eric Seidel 是WebKit 项目中非常有名的开发者,早年在 Apple 开发 WebKit,2008 年跳槽去了 Chrome 团队,十多年来一直从事Chrome 的开发, 在他的一次访谈中透漏了一些Flutter的一些信息 ,Flutter最初目的是提高web应用程序的体验 ,于是开始内部试验,是基于chrome代码移除了很多功能,比如移除一些兼容性的代码,以及web开发中一些不常用的功能,甚至改了渲染机制 不再兼容web程序,。,,跑了些benchmarks发现性能提升20倍。为了能够做更多的事情,又增加了很多功能,经过三次大的调整之后就成了现在的Flutter。Flutter也致力于提供高性能移动端跨平台App的开发体验,至于为什么 Flutter 会选择 Dart ?,除了Dart一系列有点(语法简单,同时支持AOT和JIT、速度快等)官方还说一个原因是是两个团队离的近。Flutter主要优点如下(可以概括为 简单、高性能、全平台的UI开发体验以及谷歌的大力支持)

主要优点

  • 跨平台 基于Skia绘图引擎实现全平台UI绘制,Chrome、Chrome OS、安卓、火狐浏览器、火狐操作系统以及其它许多产品都使用它作为图形引擎。 Flutter目标是跑在android iOS web linux mac windows,同时 也是作为谷歌未来系统fuchsia的御用的UI Kit(当然Flutter目前的重点还是在移动设备)。感觉这是要重新定义新标准的节奏。并且全平台的支持都是谷歌官方自己出的方案(RN官方只是支持iOS 和android。桌面和web都是社区给的方案)Flutter也是谷歌内部多个Team的合作的作品(Dart、 Flutter、 chrome等)
  • HotReload 改了代码秒见效果。对开发调试效率有了巨大的提升
  • 性能: 旨在提供 60fps的刷新率,对于刷新率 120Hz 以上的设备上能达到 120fps。
  • Dart。 生来背着“灭掉JS,替换Java”的使命,前几年一直不是很火,最近谷歌开始重视起来。还专门为Flutter 进行Dart的优化,在Rlease模式下直接将Dart编译成本地机器码,避免解释代码执行带来的性能消耗。另外Dart语法简洁,比Java和OC写起来简单太多。异步单线程完全是前端的玩法,思路简单, 不像JAVA中那种新建一个线程请求数据,之后回到主线程来操作UI。
  • 非常丰富的widget库。举个例子:比如列表拖动,也有现成的widget ReorderableListView,对material design支持也非常好,对iOS的支持也有cupertino主题
  • React style。 Flutter官方也表明过其设计思想最初也是受React个启发,一切都是Widget,没有像android iOS 那些些activity fragment 杂七杂八的概念,写应用的模式与React几乎是一模一样,写的多了感觉就是用Dart写React。Flex布局思想可以直接用、React的Component 和 PureComponent,对应Flutter里面有StateFullWidget 和 StateLessWidget,Context 对应Flutter中的 inheritWidget,状态管理redux 对应Flutter_Redux,React里面可以用RxJS,Flutter里面可以用RxDart,都是Reactive UI风格、都是基于虚拟DOM实现UI更新,甚至React新出的Hooks,在Flutter 里面也有了第三方的支持-Flutter_hooks。个人感觉相比React Native 。Flutter才是真正的在Native App中React思想的实现,实现了曾经我对RN的一些期待(比如高频率交互动画)
  • 响应式UI,数据绑定到UI,数据改变后“刷新”UI,不需要获取UI某个元素,手动去更新UI。
  • Flutter SDK 高度自由灵活,上层有丰富UI套件,除了Material Design的主题之外 还有一套iOS的主题的配套组件,除此之外,对于复杂UI 自己也可以从底层Canvas入手 自己来绘制。灵活度堪比系统的SDK。
  • 开发工具 Android Studio, IntelliJ,VS Code都提供了Flutter的开发插件,且完善度很高,自动提示用起来也非常爽。支持断点调试,堆栈信息查看,直接跳入源码等 。
  • 提供了一套与系统SDK通信的机制 (channel)
  • 文档,官方文档 API文档 也是非常完善,也为其他开发者(android iOS web reactnative Xamarin) 准备了详细的文档,可以对照学习,UI的思想都差不多。帮助其他的开发者快速入坑Flutter,文档完善度方面这点要比RN强不少了。还有中文翻译文档。以及源码里面的注释即文档。
  • 社区 目前有很多学习资料可供参考,谷歌官方也有一些视频。后面会附上链接。(信息过剩的时代,不好的信息也越来越多,甄别高质量的信息也非常重要,否则容易被淹没在一个偏角落里面,不把事件浪费在重复以及没有营养的信息上)

不足

开黑模式

  • 截止目前(2019年 1月初) 。Flutter在 github上issue, 处于open状态的有些多 ,数量在4k以上 ,closed 为1.1W。相比RN的数据则为600+ 和1.4W。当然也从另一个方面反映了Flutter受关注度很大,毕竟也是从18年开始火起来的,官方还没来得及解决。这个数据半年后再看
  • 在开发过程中遇到两个问题在模式下工作正常 在release模式下,无法work。 并在release模式下调试体验不好。debug 与release模式下运行渲染效果不一样。并且一旦发生了这种问题,调试起来也很棘手,一般跟底层机制有关 比如我最近遇到的这个问题 issues-23339
  • 虽然号称高性能,但目前综合一些评测评测以及个人体验来看,debug模式下有的卡顿问题,在release模式下基本可以做到流畅, 但距离真正的Native 还是有些差距。
  • UI写法,写不好容易发生多层次嵌套,形成嵌套地域,可读性也不高,很快看不懂自己写代码了,写UI感觉XML更舒服一些,github也开了两个issue 建议出一套类似JSX的UI规范11609 issues-15922 被否了,有第三方搞出来一个DSX
  • Webview: Flutter本身不提供自绘的webview组件,利用Platform view的能力,使用Native UI层面的组件,以Plugin的形式提供, 可以使用Flutter社区提供的flutter_webview_plugin插件,本质通过使用系统SDK的webview来实现,这样可以使用Dart对webview进行基本的操作,但是并没有提供Dart 和 JavaScript通信机制以及对Webview发出请求的拦截,当然开发者完全可以自己去定义,webview 跟系统SDK通信,然后系统SDK使用channel机制与Dart通信,目前支持的Dart与webview的交互也是这种套路。
  • 地图 国内的地图官方还没有提供Flutter的SDK, 通过包装Native的SDK结合Platform view 来实现,可以参考文档 阿里云云栖社区:在Flutter中嵌入Native组件的正确姿势是… 、 Exploring Google Maps in Flutter

  • 图片缓存,Flutter的Image组件本身不支持离线缓存(支持运行时最大1000张图片以及上线100M运行时缓存),比如浏览过的图片,断网重启APP查看,无法加载了,可以结合第三方插件cached_network_image。

  • 有时候Hotreload不生效,需要重启运行方可。
  • 与现有的App 集成起来坑不少。
  • 异常错误提示不是很友好,排查错误的体验不好
  • 实战了一个例子, Release打包之后 Android下有 6M。iOS打包之后有12M。这个包不算小了。

总结,小问题不少,但没有太大的硬伤,随着时间一些问题应该可以解决,或者被慢慢接受。

小结 :Flutter 虽有不少问题,但谷歌支持力度很大,对于有React经验的同学 上手也是非常容易的。当然相比之下RN的最大优势是动态化:苹果开发者协议允许动态下发JavaScript代码。目前Flutter在iOS下没有很好的动态化方案,相关issue讨论
很难说Flutter是否是未来的趋势,但是我相信,简单化一定是未来的趋势。
另外Hummingbird(Flutter web版代号)release之后,可发挥的空间更大,比如写个编辑器用Hummingbird在web端预览,然后拖拉拽一把梭生成native的主流程。Flutter可以收割一波Web开发者
另外就是Fuchsia 这个系统不知道谷歌会有什么态度,如果谷歌大力支持的话,应该也能为Flutter带来不少流量。

2019-01-18 更新一下: Flutter 2019的RoadMap出来了,对刚才说的那些不足进行完善

  • 增强基础设施 完善生态、工具等来提高开发体验更好的与现有的app集成
  • 支持动态更新(Android下支持从sever端下发代码
  • 发布Web版(继续试验桌面版)
  • 其他 bug修复、性能优化、完善文档 完善webview和map 支持 local notifications 以及 local data storage. 、提高错误排查体验 等 总之不断变的更好

学习路线以及资料。
学习新东西可能会比较慢,这也是值得庆幸,把自己不懂的东西看懂 就是进步,人的能力的提高也是这个过程,先弄懂什么,然后在研究怎么用,然后再去看源码。资料非常多,质量也非常高,阅读资料的之后,最重要的是写代码练习,理解原理重要 敲代码也很重要。

其他Flutter中文学习资源

状态管理

状态管理有 scopemodal、redux、rx.dart,bloc 以及mobx 几种方式,其中bloc是谷歌推荐的模式

Dart 语言基础总结

Dart 语言基础总结

Dart 是谷歌推出的面向对象的强类型语言,在2011年发布,一直不温不火。最近Flutter的出现,让Dart又起死回生。Dart支持JIT 和AOT 两种编译方式。JIT在开发环境中使用,让APP方便实现Reload,AOT在生产环境中使用,来保证较高的性能。关于AOT和JIT dart支持Flutter、Web、以及Server端开发

体验Dart功能可以在dartpad进行, 以及入门文档

开始

每个程序的执行都以main函数开始,main是Dart程序的入口。

1
2
3
void main(){

}

打印日志 dart

表达式要求必须结尾加分号

1
2
3
void main(){
print("Hello Word");
}

一些重要概念

  • 一切都是对象, Dart里面一切变量都是object、每一个object都是class的实例、。数字、布尔、函数、null 都是以对象的形式存在,所有的对象都继承于 Object
  • dart虽然是强类型的语言,但是支持类型推断,在定义变量的时候可不写变量的类型。
  • 支持泛型
  • 函数是“一等公民”,可以作为变量在代码间到处传递,也可以进行函数嵌套。每一个函数都有返回值,默认返回null(这点与JavaScript类似)
  • 在class 中以 下划线开头的属性,为私有属性。
  • 变量名 只能以字母和下划线开头,后面可以跟这数字、英文字母、下划线。

变量声明

变量声明之前一般要加上变量的类型,变量声明后未赋值之之前默认值为null。 像 int a String s。也可以通过 var 让程序动态的推测类型,类型一旦确认后,不可再赋值其他类型的数据。

通过 dynamic 声明的变量,可以在运行时变更类型 比如

1
2
3
4
void main(){
var name = 'kk'; // 效果与String name ='kk' 等同
name = 1; //编译报错
}

1
2
3
4
5
void main(){
dynamic name = 'kk';
name=1;
print(name); //1
}

如果我们不打算改变一个变量的值可以 使用 final 或者 constconstfinal更加严格,const必须在编译时知道这个常量的值。final必须在变量声明是进行初始化,final只能被赋值一次,可以是常量以及动态计算的结果值

1
2
3
4
5
6
7
8
int Func() {
// 代码
}

final int m1 = 60;
final int m2 = Func(); // 正确
const int n1 = 42;
const int n2 = Func(); // 错误,在编译的时候无法确定值。

内置类型

Dart支持以下下内置类型

  • numbers 数字
  • strings 字符串
  • booleans 布尔
  • lists(arrays) 列表/数组
  • maps 字典
  • runes
  • symbols

Dart里面 所有的数据类型都属于对象类型,每个类型都有对应的构造函数,比如可以使用 Map 来构造一个,map

数字类型

包含两种 intdouble

  • int 根据不同的平台最大64位,取值范围为 values can be from -2的63次方 到 2的63次方 - 1. 如果便以为JavaScript 则遵循javascript数值类型的规则,取值范围 -2的53次方 到 2的53次方 - 1.
  • double 遵循 IEEE 754 标准的浮点数。 与JavaScript的数字类型一样

数字与字符串类型转换 int.parse 1.toString()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// String -> int
var one = int.parse('1');
assert(one == 1);

// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);

// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');

// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');

字符串

  • 基于UTF-16编码规则。定义字符串可以使用双引号或者单引号。与JavaScript一致。
  • 可以使用 ${变量}的形式实现字符串插值。实现拼接字符串。字符串可以通过+ 拼接,字符串与数字不能相加。Dart里面不需要使用反引号,这点与JS不同。
  • 可以使用三个单引号或者三个双引号实现多行的字符串。如
1
2
3
4
5
6
7
var s1 = '''
You can create
multi-line strings like this one.
''';

var s2 = """This is also a
multi-line string.""";
  • r前缀来表示原始的字符串 比如
1
var s = r'In a raw string, not even \n gets special treatment.';

布尔值

包含两个object truefalse .受限于Dart类型安全限制,在if判断条件判断以及assert接受的值必须是布尔类型的

List

Dart里面数组被称为列表对象,可以像JavaScript中的方式来定义列表,通过设置length可以改变数组的大小(与JavaScript一致)。比如

1
var l = ['张三','李四','王五'];

Map 。键值对的对象被称为 Map,Key可以为任何类型的对象,但不能重复。可以通过字面量 也可以通过 Map关键字来定义

1
2
3
4
5
6
7
8
9
10
var gifts= {
'first':'partridge',
'second':'turtledoves',
'fifth': 'golden rings'
}

var gifts2 = Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';

runes

Dart 中 runes 是 UTF-32 字符集的 string 对象。
Unicode是一套字符集,涵盖了目前人类使用的所有字符, 为世界上的每一个字符提供一个唯一的数字编号(Code Point)来表示,目前字符集还对应不同的编码方案(比如UTF-8,UTF-16.UTF-32等),来方便计算机还存储,同一个字符用不同的编码方案对应的字节表示不同,由于Dart字符串采用的是UTF-16编码规则,如果要表示UTF-32编码的字符 需要用一些特殊的语法。通常情况使用 \uXXXX 来表示一个码点,这里的XXXX是一个4位的16进制值,例如 ♥字符的码点是 \u2665,对于大于或者小于 4位16进制的情况下,使用大括号来包裹数字 ,如😆表情符号是 \u{1f600}
字符串类型有几个属性可以来提取rune的信息,codeUnitAt 用来获取 UTF-16 字符集的字符。使用runes 来获取 UTF-32 字符集中的字符。使用runes可以获取字符串的rune rune更多API参考

1
2
3
4
var a ='😆好好学习,';
print(a.codeUnitAt(0)); // 55357
print(a.codeUnits);//[55357, 56838, 22909, 22909, 23398, 20064, 44]
print(a.runes.toList());//[128518, 22909, 22909, 23398, 20064, 44]

Symbol 不常用 ,在Dart中是不透明的,保存对人的可读的字符串以及被计算机优化过的字符串的的联系,用来表示反射后的元数据信息 。可以给类名以及函数名 声明为 symbol类型,一般用于反射操作 可以参考>>

函数 每个函数都属于Function类的实例,函数可以作为值赋值为一个变量,可以作为参数传递、也可以作为函数的返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int Add(int a,int b) {
return a+b;
}
//可以忽略返回值类型
int Add(int a,int b) {
return a+b;
}
//也可以使用类似ES6中的 箭头函数
int Add(int a,int b)=>a+b;
//函数作为参数
list.forEach((item) => print(item));

// 作为返回值
Function makeAdder(int addBy) {
return (int i) => addBy + i;
}
// 调用的时候可以指定参数的名称
int Add({int a,int b})=>a+b;
// Add(a:1,b:2)

const Scrollbar({Key key, @required Widget child}){} // @required指定必填的参数

// []指定可选参数
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}

//支持给参数默认值
int Add({int a=1,int b=1})=>a+b;
Add(a:3) //4

// 匿名函数
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});

main 程序的入口、每个程序顶部必有一个main函数 返回值为 void,有默认的 List<String>类型的参数。

词法作用域(静态作用域),JavaScript类似,在编写代码的时候就决定了变量的作用域

闭包 函数内部访问外包的变量,外包的变量无法得到释放。与JavaScript闭包类似。

1
2
3
4
5
6
7
8
9
10
11
Function addCount(){
int count =0;
return ()=>count++;
}
void main(){
var countFn = addCount();
int a=countFn();
int b = countFn();
print(a); //0
print(b); //1
}

操作符 & | ~ ++ -- + - * == >= 等等之类的,这个跟其他语言没啥区别不提了 (dart中没有 ===)

层叠访问符号 (JS中没有这个),可以连续访问同一个对象的属性

1
2
3
4
5
6
7
8
9
10
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));

//等同于
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));

控制语句

  • if/else if/else
  • while、 do-while、
  • switch/case
  • for
  • break/continue
  • Assert

异常 Throw/Catch/Finally

类 Class

  • 实例变量 构造

    1
    2
    3
    4
    5
    6
    7
    class Point {
    num x; // 实例变量 默认为 null
    num y=0; //初始值为0
    }

    var point = Point();
    point.x = 4; // 赋值
  • 构造函数 可以在类内部声明一个与类名一样的成员函数作为函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Point {
    num x, y;
    Point(num x, num y=0) {
    this.x = x;
    this.y = y;
    }
    }
    // 上面的代码可以简单为
    class Point {
    num x, y;
    Point(this.x, this.y=0);
    }
  • 命名的构造函数,命名的构造函数不能被继承,需要自己手动调用

1
2
3
4
5
6
7
8
9
10
class Point {
num x, y;

Point(this.x, this.y);

Point.origin() {
x = 0;
y = 0;
}
}
  • 重定向构造函数,

    1
    2
    3
    4
    5
    class Point {
    num x, y;
    Point(this.x, this.y);
    Point.alongXAxis(num x) : this(x, 0);
    }
  • 如果在对象不会在运行时被修改,可以定义为常量

    1
    2
    3
    4
    5
    class ImmutablePoint {
    static final ImmutablePoint origin = const ImmutablePoint(0, 0);
    final num x, y;
    const ImmutablePoint(this.x, this.y);
    }
  • 工厂构造函数 使用 factory 声明工厂构造函数,可以使用缓存机制避免不断创建新的实例,工厂构造函数不能访问this

  • 成员方法、以及静态方法,静态属性
  • 属性 Getters and setters (与JS中的类似 )赋值或者取值的时候 自动会调用方法
  • 抽象类 抽象方法 。abstract关键字前缀,抽象方法只能存在于抽象类中,用来定义接口。不实现具体的工作。
  • 显式定义接口,类可以作为接口,通过 关键字 implements来实现接口,对应的类,必须实现接口中的所有方法以及属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // A person. The implicit interface contains greet().
    class Person {
    final _name;
    Person(this._name);
    String greet(String who) => 'Hello, $who. I am $_name.';
    }

    // 必须实现接口中的所有方法属性
    class Impostor implements Person {
    get _name => '';
    String greet(String who) => 'Hi $who. Do you know who I am?';
    }
  • 使用 extends 来扩展类。

  • 支持重载成员方法override,以及对操作符的重载
  • noSuchMethod。如果用户调用类中不存在的成员方法,可以给出提示 重载 noSuchMethod
    1
    2
    3
    4
    5
    6
    7
    class A {
    @override
    void noSuchMethod(Invocation invocation) {
    print('You tried to use a non-existent member: ' +
    '${invocation.memberName}');
    }
    }
枚举类型 Enumerated types ,每个值 都有一个index属性,从 0开始计数。 Color.values拿到所有的值,可以把在switch/case语句里面把枚举当做判断条件
1
2
enum Color { red, green, blue }
Color.red.index == 0

在扩展对象的同时 还可以使用 mixins功能给对象增加功能

泛型 用法与其他高级语言中的泛型一样 允许程序员在强类型程序设计语言中编写代码时定义一些可变的类型,那些部分在使用前必须作出指明。Map Listxxi都基于泛型,具有相似功能的类,可以通过泛型实现,来避免代码的重复,提高抽象程度。可以定义泛型类 以及泛型的方法

1
2
3
4
5
6
7
8
9
10
11
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // Err


var names = <String>['张三', '李四', '王五'];
var pages = <String, int>{
'张三': 11,
'李四': 12,
'王五': 13
};

模块化

  • 使用 import 导入模块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import 'package:lib1/lib1.dart';
    import 'package:lib2/lib2.dart' as lib2;

    // Uses Element from lib1.
    Element element1 = Element();

    // Uses Element from lib2.
    lib2.Element element2 = lib2.Element();
    `
  • 部分导入

    只导入foo 模块
    1
    2
    3
    import 'package:lib1/lib1.dart' show foo;
    // 导入 foo 之外的模块
    import 'package:lib2/lib2.dart' hide foo;
  • 懒加载。在运行时按需加载用到的模块,适用于如下场景:

  1. 减小App的启动时间
  2. 进行A/B测试,可选择的不同的算法实现
  3. 一些不常用的功能,没必要每次都启动
1
2
3
4
5
6
import 'package:greetings/hello.dart' deferred as hello;

Future greet() async {
await hello.loadLibrary();
hello.printGreeting();
}

这种方式 跟ES6中 的 动态加载类似 如下

1
2
3
4
5
6
7
8
9
10
11
12
//这是JavaScript的代码
function greet(){
import('./hello').then(hello) => {
hello.printGreeting()
})
}

//或者
async function greet(){
const hello=await import('./hello')
hello.printGreeting()
}

ES 6 中 import(‘./hello’) 返回的是一个Promise,Dart中的Future 跟ES6中的Promise类似,同时Dart中也有 async/await 与ES7中的async/await 功能类似

异步支持 ,

对于异步的处理与 ES中的类似

另外提一下 Future.delayed 可以异步延时执行代码,不支持取消, 我们Timer 来实现 JavaScript setTimeout操作,支持取消

1
Future.delayed(const Duration(milliseconds: 10), ()=>print('hello world'));
1
2
3
4
5
6
7
8
import 'dart:async';

void main(){
Timer(const Duration(milliseconds: 10), ()=>print('hello world'));
Timer timer= Timer(const Duration(milliseconds: 10), ()=>print('0'));
print('1');
timer.cancel(); //输出结果 1 hello world
}

http请求 使用 dart:io 中的 HttpClient

1
2
3
4
5
6
7
8
9
import 'dart:io'
HttpClient client = new HttpClient();
client.getUrl(Uri.parse("http://www.example.com/"))
.then((HttpClientRequest request) {
//do something
return request.close();
})
.then((HttpClientResponse response) {
});

Generators: 包含异步/同步两种generator 、与ES6中的类似

typedef: 自定义新的类型,与C中的typedef类似

Dart支持注解编程

注解用与Java中的注解 或者ES6中的 Decorator类似,内置了两个注解 @deprecated @override.

isolate: 隔离的代码执行环境,不同的isolate无法共享内存

小结

学习了Dart的基础语法,感觉如果有其他的编程语言的话学起来 还是比较容易的,。Dart是一种强类型的语言,里面一切都是对象。Object是任何对象的基类。支持类型推断、支持泛型,让代码能减轻不少,支持接口编程、注解编程、Mixin。支持模块的按需加载。isolate提供了基于event-loop单线程模型,异步操作支持Future、async/await来写出同步化的代码。Dart支持AOT和JIT两种编译方式,保证了较好的开发体验,以及较高性能的线上模式。基本上掌握了这些可以上手撸Flutter了,Dart深入文档查看官方文档,有些API可能记不住的话可以去API文档查看。Dart 包基于Pub管理的,类似NodeJS中的NPM需要什么功能可以去Pub上去搜 https://pub.dartlang.org/

构造对象可以不写new,语句结尾记得加分号;;;;