[讀書筆記 Flutter 實戰 004] Dart 語言簡介


Posted by PGYW on 2021-05-26

基本語法

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-变量声明


#flutter iOS Android







Related Posts

變數常數命名

變數常數命名

week12 HW 留言板

week12 HW 留言板

MTR04_0726

MTR04_0726


Comments