基本語法
Variable
var
var t;
t = 'Hellow world';
dynamice 與 Object
Object 是 Dart 所有類別的父類別,包含 Function 和 Null。
dynamic用於型別宣告,告知編譯器,在run time的時候才會決定資料型別。
dynamic t;
Object x;
t = "hi world";
x = 'Hello Object';
//以下的assign編譯器是不會報錯的
t = 1000;
x = 1000;
以上的Code編譯器是不會報錯的。變數x是Object型別,int與String皆是Object的子類別,對編譯器來說都是Oject型別。dynamic則是特殊字,能夠代表任何型別。另外,dynamic則是有任何可能的method與property,使用任何函數或是property在編譯期間都沒有問題,而Object在編譯的階段對編譯器來說是Oject這個類別,僅能使用這個類別的method與property。
final 和 const
final 只能被設置一次,const是編譯的時候就決定好,不可以被改變。final 用於 class 中初始化就決定數值的變數宣告滿適合的。const就適合用在系統定義的內容。
函數
Dart 是物件導向語言,連函數都是物件,並有 Function 這個類別。
函數宣告
<回傳型別> <函數名稱>(<parameter型別> <parameter>) {
...
}
example
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
若沒有宣告回傳型別,該函數的回傳值會默認宣告為dynamic,函數的回傳值是沒有型別推斷的。
typedef bool CALLBACK();
//不指定返回类型,此时默认为dynamic,不是bool
isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
void test(CALLBACK cb){
print(cb());
}
//报错,isNoble不是bool类型
test(isNoble);
單行函數宣告
bool isNoble (int atomicNumber)=> _nobleGases [ atomicNumber ] != null ;
函數宣告為變數
var say = (str) {
print(str);
};
say("hi world");
函數宣告為參數
void execute(var callback) {
callback();
}
execute(() => print("xxx"))
可選位置參數
可以選擇是否要傳入該參數,未傳入的話該類別將會設定為null
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
say('Bob', 'Howdy'); //结果是: Bob says Howdy
say('Bob', 'Howdy', 'smoke signal'); //结果是:Bob says Howdy with a smoke signal
可選命名參數
可以選擇是否要傳入該參數,未傳入的話該類別將會設定為null
//设置[bold]和[hidden]标志
void enableFlags({bool bold, bool hidden}) {
// ...
}
enableFlags(bold: true, hidden: false);
不可以同時使用可選命名參數與可選位置參數
異步
Future
處理異步操作,只會對應一個結果,成功或失敗。
Future.then
獲得成功的結果後,會執行then。
Future.delayed(new Duration(seconds: 2),(){
return "hi world!";
}).then((data){
print(data);
});
失敗需要獲取error也可以帶入onError參數
Future.delayed(new Duration(seconds: 2), () {
//return "hi world!";
throw AssertionError("Error");
}).then((data) {
print("success");
}, onError: (e) {
print(e);
});
Future.catchError
執行失敗後會執行catchError。
Future.delayed(new Duration(seconds: 2),(){
//return "hi world!";
throw AssertionError("Error");
}).catchError((e){
//执行失败会走到这里
print(e);
});
Future.whenComplete
無論成功失敗都會執行。
Future.delayed(new Duration(seconds: 2),(){
//return "hi world!";
throw AssertionError("Error");
}).then((data){
//执行成功会走到这里
print(data);
}).catchError((e){
//执行失败会走到这里
print(e);
}).whenComplete((){
//无论成功或失败都会走到这里
});
Future.await
有時會需要一次打兩個或更多的api,但需要拿到所有的reaponse才能開始將資料組合再顯示到UI上,因此就需要wait啦。注意,任一api回傳有錯誤,都直接進入error,不會近入then。
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);
});
結果是hello world
async / await
Callback Hell
//先分别定义各个异步任务
Future<String> login(String userName, String pwd){
...
//用户登录
};
Future<String> getUserInfo(String id){
...
//获取用户信息
};
Future saveUserInfo(String userInfo){
...
// 保存用户信息
};
login("alice","******").then((id){
//登录成功后通过,id获取用户信息
getUserInfo(id).then((userInfo){
//获取用户信息后保存
saveUserInfo(userInfo).then((){
//保存用户信息,接下来执行其它操作
...
});
});
})
以上就是Callback Hell,除錯神難。基本上有兩種方法解決這個問題。
使用Future消除Callback Hell
login("alice","******").then((id){
return getUserInfo(id);
}).then((userInfo){
return saveUserInfo(userInfo);
}).then((e){
//执行接下来的操作
}).catchError((e){
//错误处理
print(e);
});
使用async/await消除Callback Hell
task() async {
try{
String id = await login("alice","******");
String userInfo = await getUserInfo(id);
await saveUserInfo(userInfo);
//执行接下来的操作
} catch(e){
//错误处理
print(e);
}
}
async/await都是語法糖,編譯器或是解釋器最後都會將他轉化為Future。
Stream
用於接受異步事件,跟Future不同的是,可以接收多個異步的結果。
Stream.fromFutures([
// 1秒后返回结果
Future.delayed(new Duration(seconds: 1), () {
return "hello 1";
}),
// 抛出一个异常
Future.delayed(new Duration(seconds: 2),(){
throw AssertionError("Error");
}),
// 3秒后返回结果
Future.delayed(new Duration(seconds: 3), () {
return "hello 3";
})
]).listen((data){
print(data);
}, onError: (e){
print(e.message);
},onDone: (){
});
I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3
Ref:
https://book.flutterchina.club/chapter1/dart.html#_1-4-1-变量声明