前言
因为flutter使用的是dart语言,所以需要对dart作一定的学习
flutter官方文档: 链接教程
基础
变量声明
var
类似JS中的var,可以接受任何类型的变量
最大的不同是Dart中var变量一旦赋值,类型便会确定,不能改变其变量(thanks for inventing Javascript)
因为Dart是强类型语言,而JS是弱类型脚本语言
Object 和 dynamic
Object是所有对象的根基类,所有类都是Object的子类
dynamic与var一样可以赋值任意对象,但是dynamic赋值的变量在赋值后可以后期改变变量类型(Object也可以)
dynamic t;
Object x;
t = "hi world";
x = 'Hello Object';
//下面代码没有问题
t = 1000;
x = 1000;
dynamic声明的对象编译器会提供所有的组合,而Object声明的对象只能使用Object的属性与方法
final与const
一个final变量只能被设置一次
- const变量是一个编译时常量
- final变量在第一次使用时被初始化
- 被这两种类型修饰的变量,可以忽视类型
函数
- Dart中函数也是对象,且有一个类型
Function
- 因此函数可以赋值给变量或者作为参数传递给其他函数
- Dart中的函数如果没有显式声明返回值类型时会默认当成
dynamic
来处理 - 函数返回值没有类型推断
对于只包含一个表达式的函数,可以使用简写语法
bool isNoble (int atomicNumber)=> _nobleGases [ atomicNumber ] != null ;
函数作为参数范例(来自官方文档)
void execute(var callback) {
callback();
}
execute(() => print("xxx"))
可选的位置参数
包含一组函数参数,用[]
标记为可选的位置参数,并放在参数列表的最后面
范例(来自官方文档)
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
可选的命名参数
定义函数时,使用{param1, param2, ...}
放在参数列表的最后面用于指定命名参数
//设置[bold]和[hidden]标志
void enableFlags({bool bold, bool hidden}) {
// ...
}
调用函数时,可以用指定命名参数 paramName : value
enableFlags(bold: true, hidden: false);
不能同时使用可选的位置参数与可选的命名参数
异步支持
Dart类库有非常多的返回Future
或者Stream
对象的函数,这些函数被称为异步函数
async
与await
关键词支持异步编程
Future
与Javascript中的Promise
相似,表示一个异步操作的最终完成(失败)及其结果值的表示
一个Future只会对应一个结果,要么成功要么失败
Future.then
下方Duration函数将会在延时2s之后返回字符串"hi world!"
而 在then
中接收异步结果并打印结果
Future.delayed(new Duration(seconds: 2),(){
return "hi world!";
}).then((data){
print(data);
});
Future.catchError
倘若异步任务发生错误,可以在catchError
中捕获错误
Future.delayed(new Duration(seconds: 2),(){
//return "hi world!";
throw AssertionError("Error");
}).then((data){
//执行成功会走到这里
print("success");
}).catchError((e){
//执行失败会走到这里
print(e);
});
捕获错误还可以直接用then
方法中的可选参数 onError
Future.delayed(new Duration(seconds: 2), () {
//return "hi world!";
throw AssertionError("Error");
}).then((data) {
print("success");
}, onError: (e) {
print(e);
});
Future.whenComplete
就是无论异步失败还是成功,都会执行的内容,比如弹出对话框,除了在两个内容内都加上对应操作之外,
直接添加whenComplete
进行回调是一种更省事的方法
Future.delayed(new Duration(seconds: 2),(){
//return "hi world!";
throw AssertionError("Error");
}).then((data){
//执行成功会走到这里
print(data);
}).catchError((e){
//执行失败会走到这里
print(e);
}).whenComplete((){
//无论成功或失败都会走到这里
});
Future.wait
该函数中接受一个Future数组参数
,只有数组中所有Future都执行成功后,才会触发then
的成功回调,任意一个Future执行失败都会触发错误回调
下列通过两个Future.delayed
来模拟两个数据获取的异步任务
Future.wait([
// 2秒后返回结果
Future.delayed(new Duration(seconds: 2), () {
return "hello";
}),
// 4秒后返回结果
Future.delayed(new Duration(seconds: 4), () {
return " world";
})
]).then((results){
print(results[0]+results[1]);
}).catchError((e){
print(e);
});
回调地狱
如果代码中有大量异步逻辑,并且出现大量异步任务依赖其他异步任务的结果时,必然会出现Future.then
回调中套回调的情况
过多的嵌套会导致代码可读性下降以及出错率提高,非且非常难维护
这是之前JS被吐槽最多的点,而后期通过
- ECMAScript6引入Promise
- ECMAScript7引入
async/await
而Dart直接兼顾了这两个解决方法
- Future相当于
Promise
- async/await还是原来的配方,连名字都一样
使用Future来消除回调地狱
Future的所有返回值都是Future对象,因此可以方便进行链式调用
倘若在then中返回的是一个Future话,该future会执行,执行结束后会触发then回调,依次向下就避免了嵌套
美中不足就是仍然存在一层回调
使用async/await来消除回调地狱
task() async {
try{
String id = await login("alice","******");
String userInfo = await getUserInfo(id);
await saveUserInfo(userInfo);
//执行接下来的操作
} catch(e){
//错误处理
print(e);
}
}
- async表示函数是异步的,定义的函数会返回一个
Future
,可用then方法添加回调函数 - await后面是一个Future,表示等待该异步任务完成,完成后才会往下走
- await函数必须在
async
函数内部
Stream
用于接收异步事件数据,与Future不同的是,它可以接受多个异步操作的结果
Q.E.D.
Comments | 0 条评论