2、flutter--Dart


  一、Dart語言簡介

  百度(玄語):

    Dart是谷歌開發的 計算機編程語言,后來被Ecma (ECMA-408)認定為標准  [1]  。它被用於web、服務器、移動應用 [2]  和物聯網等領域的開發。它是寬松開源許可證(修改的BSD證書)下的開源軟件。
    Dart是面向對象的、類定義的、單繼承的語言。它的語法類似C語言,可以轉譯為JavaScript,支持接口(interfaces)、混入(mixins)、抽象類(abstract classes)、具體化泛型(reified generics)、可選類型(optional typing)和sound type system
  白話:
    Dart 在設計時應該是同時借鑒了 Java 和 JavaScript,同時又引入了一些現代編程語言的特性。
     Dart 在靜態語法方面和 Java 非常相似。如①類型定義、函數聲明、泛型等,而②在動態特性方面又和 JavaScript 很像,如函數式特性、異步支持等。除了融合 Java 和 JavaScript 語言之所長之外,具有表現力的語法,如可選命名參數、 ..(級聯運算符)和 ?.(條件成員訪問運算符)以及 ??(判空賦值運算符)。在 Dart 中其實看到的不僅有 Java 和 JavaScript 的影子,它還具有其它編程語言中的身影,如命名參數在 Objective-C 和 Swift 中早就很普遍。

二、變量聲明

1、var

  1、類似於 JavaScript 中的var

  2、不同是 Dart 中 var 變量一旦賦值,類型便會確定,則不能再改變

2、dynamic 和 Object

  1、Object 是 Dart 所有對象的根基類,所以任何類型的數據都可以賦值給Object聲明的對象

  2、dynamicObject聲明的變量都可以賦值任意對象,且后期可以改變賦值的類型

  3、dynamicObject不同的是dynamic聲明的對象編譯器會提供所有可能的組合,而Object聲明的對象只能使用 Object 的屬性與方法, 否則編譯器會報錯

 

3、final和const

  1、從未打算更改一個變量,那么使用 final 或 const

  2、const 變量是一個編譯時常量(編譯時直接替換為常量值),final變量在第一次使用時被初始化。被final或者const修飾的變量,變量類型可以省略

//可以省略String這個類型聲明
final str = "hi world";
//final String str = "hi world"; 
const str1 = "hi world";
//const String str1 = "hi world";

4、空安全(null-safety)

  1、Dart 中一切都是對象,這意味着如果我們定義一個數字,在初始化它之前如果我們使用了它,假如沒有某種檢查機制,則不會報錯,如:

test() {
  int i; .//未初始化
  print(i*8);
}

  2、在 Dart 引入空安全之前,上面代碼在執行前不會報錯,但會觸發一個運行時錯誤,原因是 i 的值為 null 。但現在有了空安全,則定義變量時我們可以指定變量是可空還是不可空

int i = 8; //默認為不可空,必須在定義時初始化。
int? j; //  定義為可空類型,對於可空變量,我們在使用前必須判空。

// 如果我們預期變量不能為空,但在定義時不能確定其初始值,則可以加上late關鍵字,
// 表示會稍后初始化,但是在正式使用它之前必須得保證初始化過了,否則會報錯
late int k;
k=9;

  3、如果一個變量我們定義為可空類型,在某些情況下即使我們給它賦值過了,但是預處理器仍然有可能識別不出,這時我們就要顯式(通過在變量后面加一個”!“符號)告訴預處理器它已經不是null了

三、函數

1、函數聲明:如果沒有顯式聲明返回值類型時會默認當做dynamic處理,注意,函數返回值沒有類型

bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}



typedef bool CALLBACK();

//不指定返回類型,此時默認為dynamic,不是bool
isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

void test(CALLBACK cb){
   print(cb()); 
}
//報錯,isNoble不是bool類型
test(isNoble); 

2、對於只包含一個表達式的函數,可以使用簡寫語法

bool isNoble (int atomicNumber)=> true ;  

3、函數作為變量

var say = (str){
  print(str);
};
say("hi world");

4、函數作為參數傳遞

void execute(var callback) {
    callback();
}
execute(() => print("xxx"))

5、可選的位置參數

//包裝一組函數參數,用[]標記為可選的位置參數,並放在參數列表的最后面:
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

6、可選的命名參數

定義函數時,使用{param1, param2, …},放在參數列表的最后面,用於指定命名參數。例如:
//設置[bold]和[hidden]標志
void enableFlags({bool bold, bool hidden}) {
    // ... 
}

調用函數時,可以使用指定命名參數。例如:paramName: value
enableFlags(bold: true, hidden: false);

四、mixin

Dart 是不支持多繼承的,但是它支持 mixin,簡單來講 mixin 可以 “組合” 多個類,我們通過一個例子來理解。

定義一個 Person 類,實現吃飯、說話、走路和寫代碼功能,同時定義一個 Dog 類,實現吃飯、和走路功能:我們定義了幾個 mixin,然后通過 with 關鍵字將它們組合成不同的類。有一點需要注意:如果多個mixin 中有同名方法,with 時,會默認使用最后面的 mixin 的,mixin 方法中可以通過 super 關鍵字調用之前 mixin 或類中的方法。

class Person {
  say() {
    print('say');
  }
}

mixin Eat {
  eat() {
    print('eat');
  }
}

mixin Walk {
  walk() {
    print('walk');
  }
}

mixin Code {
  code() {
    print('key');
  }
}

class Dog with Eat, Walk{}
class Man extends Person with Eat, Walk, Code{}

五、異步支持

Dart類庫有非常多的返回Future或者Stream對象的函數。 這些函數被稱為異步函數:它們只會在設置好一些耗時操作之后返回

asyncawait關鍵詞支持了異步編程,允許寫出和同步代碼很像的異步代碼

1、Future

Future與JavaScript中的Promise非常相似,表示一個異步操作的最終完成(或失敗)及其結果值的表示。簡單來說,它就是用於處理異步操作的,異步處理成功了就執行成功的操作,異步處理失敗了就捕獲錯誤或者停止后續操作。一個Future只會對應一個結果,要么成功,要么失敗。

由於本身功能較多,這里我們只介紹其常用的API及特性。還有,請記住,Future

 其他:待補充

六、Stream

Stream 也是用於接收異步事件數據,和 Future 不同的是,它可以接收多個異步操作的結果(成功或失敗)。 也就是說,在執行異步任務時,可以通過多次觸發成功或失敗事件來傳遞結果數據或錯誤異常。 Stream 常用於會多次讀取數據的異步任務場景,如網絡內容下載、文件讀寫等。舉個例子:

Stream.fromFutures([
  // 1秒后返回結果
  Future.delayed(Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 拋出一個異常
  Future.delayed(Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒后返回結果
  Future.delayed(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

 

七、 Dart和Java及JavaScript對比

1、Dart vs Java

客觀的來講,Dart 在語法層面確實比 Java 更有表現力;在 VM 層面,Dart VM 在內存回收和吞吐量都進行了反復的優化,但具體的性能對比,筆者沒有找到相關測試數據,但在筆者看來,只要 Dart 語言能流行,VM 的性能就不用擔心,畢竟 Google 在 Go(沒用VM但有GC)、JavaScript(v8)、Dalvik( Android 上的 Java VM )上已經有了很多技術積淀。值得注意的是 Dart 在 Flutter 中已經可以將 GC 做到 10ms 以內,所以 Dart 和 Java 相比,決勝因素並不會是在性能方面。而在語法層面,Dart 要比 Java 更有表現力,最重要的是 Dart 對函數式編程支持要遠強於 Java(目前只停留在 Lambda 表達式),而 Dart 目前真正的不足是生態,但筆者相信,隨着 Flutter 的逐漸火熱,會回過頭來反推 Dart 生態加速發展,對於 Dart 來說,現在需要的是時間。

2、Dart vs JavaScript

JavaScript 的弱類型一直被抓短,所以 TypeScript 甚至是 Facebook 的 Flow 才有市場。就筆者使用過的腳本語言中(筆者曾使用過 Python、PHP),JavaScript 無疑是動態化支持最好的腳本語言,比如在 JavaScript 中,可以給任何對象在任何時候動態擴展屬性,對於精通 JavaScript 的高手來說,這無疑是一把利劍。但是,任何事物都有兩面性,JavaScript 強大的動態化特性也是把雙刃劍,你可經常聽到另一個聲音,認為 JavaScript 的這種動態性糟糕透了,太過靈活反而導致代碼很難預期,無法限制不被期望的修改。畢竟有些人總是對自己或別人寫的代碼不放心,他們希望能夠讓代碼變得可控,並期望有一套靜態類型檢查系統來幫助自己減少錯誤。正因如此,在 Flutter中,Dart 幾乎放棄了腳本語言動態化的特性,如不支持反射、也不支持動態創建函數等。並且 Dart 從 2.0 開始強制開啟了類型檢查(Strong Mode),原先的檢查模式(checked mode)和可選類型(optional type)將淡出,所以在類型安全這個層面來說,Dart 和 TypeScript、CoffeeScript 是差不多的,所以單從動態性來看,Dart 並不具備什么明顯優勢,但綜合起來看,Dart 既能進行服務端腳本、APP 開發、Web 開發,這就有優勢了!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM