语言概述
- Dart 语言在2011年10月由 Google 发布的网络编程语言,并在2012年10月发布第一个里程碑版本M1,2015年5月Google公开了基于Dart语言的移动应用程序开发框架Sky,后更名为Flutter
- Flutter是一个使用Dart语言开发的跨平台移动UI框架,渲染引擎依赖Skia图形库实现,在Flutter中的控件树编译为高性能的本地ARM代码直接绘制。Dart是Flutter的主要开发语言 ,支持JIT编译(开发阶段可热重载)和AOT编译(Release运行阶段性能好)
- Dart可利用隔离区(Isolate)实现多线程,且不共享内存,实现无锁快速分配
- Dart采用分代垃圾回收机制,且在创建对象分配内存时,是在现有堆上移动指针,保证内存增长是线性的,有利于UI框架中大量Widgets对象的创建和销毁优化
- Dart是面向对象的、类定义的、单继承的语言,一切都是对象(包括基本类型,函数,null),所有对象都继承自Object
- Dart是强类型语言,但也自带类型推断
- Dart中没有public,private,protected,默认都是public的,可以通过_开头指定是库私有的
- Dart支持顶级变量(不与类绑定)和顶级函数(如main函数)
变量
Dart为强类型语言,变量可显式声明,也可自动推断,但推断出来后,该变量的类型将不再改变,若要让变量不被限制于一种类型,可将变量声明为dynamic或Object
类型
- 数字num
int: 平台的不同,范围也不同。整数值不大于64位。在Dart VM上,值可以从-263到263 - 1
double: 64位(双精度)浮点数
数字和字符串转换:
int.parse('1')
3.14159.toStringAsFixed(2);
- 字符串String
String是UTF-16编码单元的序列,可以使用${expression}将表达式的值放入字符串中。如果表达式是一个标识符,可以不用{},
String str = "world";
print("hello$str");
可以用三重引号创建多行字符串,用r前缀创建一个原始字符串(不会因为有\n换行)
var s = r'In a raw string, not even \n gets special treatment.';
print(s); //虽然有换行符,但输出不会换行
- 布尔型(bool):true, false
- 列表List
数组即为列表对象
var list = [1,2,3]; //推断为List<int> 类型,若添加非int对象,则会报错
- 映射Map
可以通过map字面量直接创建,也可以通过Map()构造方法创建, 类型会自动推断
var g = { 1: 'a', 2: 'b', 3: 'c'}
var g1 = Map();
g1[1] = 'a1'
final constantMap = const {2: 'b', 3: 'c'};
- 字符Runes:
字符是字符串的UTF-32编码 - 符号Symbols:
print(#bar)
// 输出 Symbol("bar")
变量声明
Dart没有public protected private等关键字,如果某个变量以下划线开头,代表这个变量是私有的
String me = "Bob"; // 显式name变量声明为String
var you = "Bob"; // 自动推断name变量为String
dynamec he = “Bob”; // 声明变量为任意类型,类似于java中Object
he = 18;
int u; // 未初始化的变量初始值为null,变量存放的是对象,对象都继承自Object类
final a; // 最终变量,只能设置一次,顶级或类变量在第一次使用时被初始化
const b = 9; // 编译时常量,定义时必须赋值。注意实例变量可以是final,但不能是const。
var f = const[];
f = [1,3]; // 可以更改一个非final的且非const变量的值,即使它曾经有一个const值
运算符
相等(==)
若两者都为空则返回true,若只有一空返回false;
需要知道两个对象是否完全相同的情况下,可以使用identical()函数
类型判断(is)
若obj 实现了T,则 obj is T 为真
类型转换(as)
as操作符将对象转换为特定类型
非空赋值(??=)
b ??= value; //仅仅在b为空的情况下b被赋值value否则b的值不变
条件表达(??)
expr1 ?? expr2 ; //如果expr1是非空的,则返回其值,否则,计算并返回expr2的值
级联(..)
在同一个对象上创建一个操作序列。可以访问同一对象上的字段,调用函数,省去创建临时变量的步骤。
不能在一个返回void结果上继续构建级联操作
querySelector('#confirm') // 获取一个对象
..text = 'Confirm' // 使用它的成员
..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!'));
条件成员访问(?.)
如果左边的操作对象为null则返回null,否则返回右边的成员
函数
函数也是对象,可以赋给函数,也可以赋给变量,甚至可以是函数的返回值。函数可以省略返回类型声明(可以根据return自动推断),所有函数都默认返回null(没有return语句)
函数简写
isBelowZero(int n) => n < 0; //只包含一个表达式的函数简写
命名参数
在定义函数时,使用{param1, param2,…}来指定命名参数
void enableFlags({bool bold, bool hidden}) {...}
enableFlags(bold: true, hidden: false);
可选参数
在普通的位置参数里,可以通过[]包装为一组可选参数,在命名参数里,可以通过@required标识必传参数,其他都是可选的。
say(String from, String msg, [String device])
Scrollbar({Key key, @required Widget child})
默认参数
用 = 来定义参数的默认值。默认值必须是编译时常量。如果没有提供默认值,则默认值为null
void enableFlags({bool bold = false, bool hidden = false})
main()函数
应用程序的入口点。返回void,并有一个可选的列表参数作为参数
void main(List<String> arguments) {
print(arguments);
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
匿名函数
([[Type] param1[, …]]) {
codeBlock;
};
函数类型
typedef为函数提供一个类型别名
typedef Compare<T> = int Function(T a, T b);
int sort(int a, int b) => a - b;
void main() {
assert(sort is Compare<int>); // True!
}
流程控制
循环迭代
//若对象是可迭代的
candidates.forEach((candidate) => candidate.interview());
//List和Set等支持for in迭代
for (var x in collection) { }
过滤器where
即使where筛选后为空也没问题,只是不会执行后面的forEach
candidates
.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());
switch
每个非空的case子句以一个break语句结束,否则会报错,default 可以没有。
类和库
Dart值支持单继承,所有类都是Object的子类,支持泛型。库的导入用import
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2; //导入有冲突时指定前缀
import 'package:lib1/lib1.dart' show foo; //只导入foo
import 'package:lib2/lib2.dart' hide foo; //除了foo其他导入
import 'package:greetings/hello.dart' deferred as hello; //延时加载
Future greet() async {
await hello.loadLibrary(); //需要时加载,可以在库上多次调用loadLibrary()。该库只加载一次
hello.printGreeting();
}
类实现call方法,则可以通过类对象直接调用函数
class WannabeFunction {
call(String a, String b, String c) => '$a $b $c!';
}
var wf = new WannabeFunction();
var out = wf("Hi", "there,", "gang");
print('$out');
异步
async和await
通过将函数体用async修饰符标记,将使其返回一个Future,声明异步函数。如果异步函数没有返回一个有用的值,那么将其返回Future
String lookUpVersionSync() => '1.0.0'; //同步函数
Future<String> lookUpVersionAsync() async => '1.0.0';; //异步函数
Future checkVersion() async {
var version = await lookUpVersionAsync();
}
隔离器(Isolate)
不同于线程,所有Dart代码都运行在隔离器内部,而不是线程。每个隔离都有它自己的内存堆,确保任何其他隔离器都不能访问隔离状态