Flutter(一) 安裝部署與認識Dart語言

推薦閱讀

 Flutter(二)Android集成Flutter項目並實現跳轉到 Flutter 界面


Flutter練習項目,非常適合入門,下面是GitHub地址,歡迎star:

https://github.com/aiyangtianci/flutter_app


目錄

一、Flutter 安裝部署

(一)在Windows上搭建Flutter開發環境

(二)在macOS上搭建Flutter開發環境

(三)使用鏡像

二、Dart語言介紹

Dart vs Java

Dart 和 Flutter

一、異步

1、Future

2、Async/await

3、Stream

二、變量聲明

1、var

2、final和const

3、dynamic和Object

三、函數

1、帶返回值函數聲明

2、函數作爲變量

3、函數作爲參數


一、Flutter 安裝部署

Flutter 是 Google推出並開源的移動應用開發框架,主打跨平臺、高保真、高性能。開發者可以通過 Dart語言開發 App,一套代碼同時運行在 iOS 和 Android平臺。 Flutter提供了豐富的組件、接口,開發者可以很快地爲 Flutter添加 native擴展。同時 Flutter還使用 Native引擎渲染視圖,一遍編寫代碼一遍查看運行效果,這無疑能爲用戶提供良好的體驗。

由於Flutter會同時構建Android和IOS兩個平臺的發佈包,所以Flutter同時依賴Android SDK和iOS SDK,在安裝Flutter時也需要安裝相應平臺的構建工具和SDK。下面我們分別介紹一下Windows和macOS下的環境搭建。

(一)在Windows上搭建Flutter開發環境

1、去flutter官網下載其最新可用的安裝包,下載地址:https://flutter.dev/docs/development/tools/sdk/releases

打開後如圖1-2所示:Beta渠道是穩定版本,Dev渠道是比較新的版本。

注意,Flutter的渠道版本會更新,請以Flutter官網爲準。另外,在中國大陸地區,要想正常獲取安裝包列表或下載安裝包,可能需要翻牆,讀者也可以去Flutter github項目下去下載安裝包,地址:https://github.com/flutter/flutter/releases 。

  • 將安裝包zip解壓到你想安裝Flutter SDK的路徑(如:C:\src\flutter;注意,不要將flutter安裝到需要一些高權限的路徑如C:\Program Files\)。
  • 在Flutter安裝目錄的flutter文件下找到flutter_console.bat,雙擊運行並啓動flutter命令行,接下來,你就可以在Flutter命令行運行flutter命令了。

2、更新環境變量

在“用戶環境變量”下檢查是否有名爲“Path”的條目:(類似添加Java環境變量,可以百度搜)

  • 如果該條目存在, 追加 flutter\bin的全路徑,使用 ; 作爲分隔符。
  • 如果該條目不存在,創建一個新用戶變量 Path ,然後將 flutter\bin 的安裝的全路徑作爲它的值。

重啓Windows以應用此更改.

3、在Flutter命令行運行如下命令來查看是否還需要安裝其它依賴:

flutter doctor

該命令檢查你的環境並在命令行窗口中顯示報告。Dart SDK已經在打包在Flutter SDK裏了,沒有必要單獨安裝Dart。 仔細檢查命令行輸出以獲取可能需要安裝的其他軟件或進一步需要執行的任務。第一次運行flutter命令(如flutter doctor)時,它會下載它自己的依賴項並自行編譯。以後再運行就會快得多。缺失的依賴需要安裝一下,安裝完成後再運行flutter doctor命令來驗證是否安裝成功。

 

(二)在macOS上搭建Flutter開發環境

要安裝並運行Flutter,您的開發環境必須滿足以下最低要求:

  • 操作系統: macOS (64-bit)
  • 磁盤空間: 700 MB (不包括Xcode或Android Studio的磁盤空間)

1、去flutter官網下載其最新可用的安裝包。https://flutter.dev/docs/development/tools/sdk/releases?tab=macos#macos

2、解壓安裝包到你想安裝的目錄,如:

cd ~/development
unzip ~/Downloads/flutter_macos_v0.5.1-beta.zip

//安裝的目錄
/Users/djmsh/Downloads/flutter

3、將Flutter/bin添加到PATH中請參考下面更新環境變量 :

a. 進入當前用戶的home目錄:
cd ~/

b. 創建.bash_profile文件:
touch .bash_profile

c. 打開.bash_profile並編輯:
open .bash_profile

d. 這樣就打開了一個記事本,會顯示你之前配置過的path,修改記事本,然後根據自己需要配置。

提示:通過defaults write com.apple.finder AppleShowAllFiles FALSE ; killall Finder命令顯示隱藏文件

//java jdk
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
export JAVA_HOME

CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export CLASSPATH

//android sdk
PATH=$JAVA_HOME/bin:$PATH:.
export PATH=${PATH}:~/android-sdk-macosx/platform-tools


//在這裏添加!flutter和dart
export PATH=~/flutter/bin:$PATH
export PATH=~/flutter/bin/cache/dart-sdk/bin:$PATH

例如:上面是我配置好的java和android環境變量。
e. command+s保存關閉文件

f. 使修改後的配置生效命令:
source .bash_profile

8.驗證環境變量是否配置成功:

例如在終端輸入以下命令:java version   或 flutter

4、運行 flutter doctor命令檢查。

缺失的依賴需要安裝一下,安裝完成後再運行flutter doctor命令來驗證是否安裝成功。

5、記得在Android的Preferences中找到插件Plugins搜索並安裝Flutter插件。

 

(三)使用鏡像

由於在國內訪問Flutter有時可能會受到限制,下載安裝會比較慢,Flutter官方爲中國開發者搭建了臨時鏡像,可以將安裝源設置成國內的。大家可以將如下環境變量加入到用戶環境變量中,設置方法和上面設置“Flutter添加到PATH”差不多。

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home
PATH=$JAVA_HOME/bin:$PATH:.
CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export JAVA_HOME
export PATH=${PATH}:~/android-sdk-macosx/platform-tools
export CLASSPATH
export PATH=/Users/djmsh/Downloads/flutter/bin:$PATH

//添加下面這兩行:
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

注意: 此鏡像爲臨時鏡像,並不能保證一直可用,讀者可以參考https://flutter.io/community/china 以獲得有關鏡像服務器的最新動態。

 

二、Dart語言介紹

Dart 是谷歌開發的計算機編程語言 ,被用於web、服務器、移動端和物聯網等領域的開發。Dart是面向對象的、類定義的、單繼承的語言。語法類似C語言和JavaScript,支持接口(interfaces)、混入(mixins)、抽象類(abstract classes)、具體化泛型(reified generics)、可選類型(optional typing) 。

2011年10月10至12日Dart在丹麥奧爾胡斯舉行的GOTO大會上亮相。由Lars bak和kasper lund創建。

2015年5月Dart開發者峯會上,亮相了基於Dart語言的移動應用程序開發框架 Sky ,後更名爲 Flutter。

Dart vs Java

在VM性能層面,Dart VM在內存回收和吞吐量都進行了反覆的優化,因此,Dart在Flutter中可以將GC做到10ms以內。畢竟Google在Go(沒用VM但有GC)、JavaScript(v8)、Dalvik(Android上的Java VM)上已經有了很多技術積澱。Dart和Java相比,決勝因素並不會是在性能方面。

在語法層面,Dart要比Java更有表現力。Dart的設計應該是同時借鑑了Java和JavaScript。Dart在靜態語法方面和Java非常相似,如類型定義、函數聲明、泛型等,而在動態特性方面又和JavaScript很像,如函數式特性、異步支持等。除了融合Java和JavaScript語言之所長之外,Dart也具有一些其它具有表現力的語法,如可選命名參數、..(級聯運算符)和?.(條件成員訪問運算符)以及??(判空賦值運算符)。

Dart目前真正的不足是生態,但筆者相信,隨着Flutter的逐漸火熱,會回過頭來反推Dart生態加速發展,對於Dart來說,現在需要的是時間。

Dart 和 Flutter

Flutter是谷歌的移動UI框架,可以快速在iOS和Android上構建高質量的原生用戶界面。 Flutter可以與現有的代碼一起工作。在全世界,Flutter正在被越來越多的開發者和組織使用,並且Flutter是完全免費、開源的。Flutter是一個使用Dart語言開發的跨平臺移動UI框架,通過自建繪製引擎,能高性能、高保真地進行移動開發。Dart囊括了多數編程語言的優點,它更符合Flutter構建界面的方式。

 

一、異步

1、Future

Future與JavaScript中的Promise非常相似,一個異步操作的最終完成或失敗及其結果值(一個Future只會對應一個結果,要麼成功,要麼失敗)。

(1)Future.then

Future.deleyed()進行延遲2秒後打印data:

Future.delayed(new Duration(seconds: 2),(){
   return "hi world!";
}).then((data){
   print(data);
});

(2)Future.catchError

如果異步任務發生錯誤,在catchError中捕獲錯誤:

Future.delayed(new Duration(seconds: 2),(){
   throw AssertionError("Error");  
}).then((data){
   //成功
   print("success");
}).catchError((e){
   //失敗
   print(e);
});

then方法還有一個可選參數onError,我們也可以它來捕獲異常:

Future.delayed(new Duration(seconds: 2), () {
    throw AssertionError("Error");
}).then((data) {
    print("success");
}, onError: (e) {
    print(e);
});

(3)Future.whenComplete

有時網絡請求前需要彈加載框,請求結束使用FuturewhenComplete回調進行關閉:

Future.delayed(new Duration(seconds: 2),(){
   throw AssertionError("Error");
}).then((data){
   //成功 
   print(data);
}).catchError((e){
   //失敗
   print(e);
}).whenComplete((){
   //請求結束
});

(4)Future.wait

有些時候需要從多個網絡接口獲取數據,獲取成功後將進行特定的處理後再顯示到UI界面上。此時應該使用Future.wait,在Future數組中執行所有Future對象都成功後,纔會觸發then的成功回調,只要有一個Future執行失敗,就會觸發catchError錯誤回調。代碼如下:

Future.wait([

  Future.delayed(new Duration(seconds: 2), () {
    return "hello";
  }),

  Future.delayed(new Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0]+results[1]);//4秒後顯示 hello world
}).catchError((e){
  print(e);
});

2、Async/await

Dart中的async/await 和JavaScript中的async/await功能和用法是一模一樣的。

回調地獄(Callback Hell):如果出現大量異步任務依賴其它異步任務的結果時,必然會出現Future.then回調中套回調情況。比如,用戶先登錄,登錄成功後會獲得用戶ID,通過用戶ID,請求用戶信息,獲取到用戶個人信息後,保存在本地。

//先分別定義各個異步任務
Future<String> login(String userName, String pwd){
    ...
    //用戶登錄
};
Future<String> getUserInfo(String id){
    ...
    //獲取用戶信息 
};
Future saveUserInfo(String userInfo){
    ...
    // 保存用戶信息 
};

login("1","1").then((id){
 //登錄成功後通過,id獲取用戶信息    
 getUserInfo(id).then((userInfo){
    //獲取用戶信息後保存 
    saveUserInfo(userInfo).then((){
       //保存用戶信息,接下來執行其它操作
    });
  });
})

這種在回調裏面套回調會導致的代碼可讀性下降以及出錯率提高,並且非常難維護,這個問題被形象的稱爲回調地獄(Callback Hell)。回調地獄問題在之前JavaScript中非常突出,也是JavaScript被吐槽最多的點,但隨着ECMAScript6和ECMAScript7標準發佈後,這個問題得到了非常好的解決,而解決回調地獄的兩大神器正是ECMAScript6引入了Promise,以及ECMAScript7中引入的async/await。 而在Dart中幾乎是完全平移了JavaScript中的這兩者:Future相當於Promise,而async/await連名字都沒改。

(1)使用Future消除Callback Hell

login("alice","******").then((id){

    return getUserInfo(id);

}).then((userInfo){

    return saveUserInfo(userInfo);

}).then((e){
   
}).catchError((e){
  print(e);
});

Future 的所有API的返回值仍然是一個Future對象,所以可以進行鏈式調用 。

(2)使用async/await消除callback hell

通過Future回調中再返回Future的方式雖然能避免層層嵌套,但是還是有一層回調。使用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  :表示等待該異步任務完成;await必須出現在 async 函數內部。

其實,無論是在JavaScript還是Dart中,async/await都只是一個語法糖,編譯器或解釋器最終都會將其轉化爲一個Promise(Future)的調用鏈。

 

3、Stream

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

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: (){

});

二、變量聲明

1、var

它可以接收任何類型的變量,但最大的不同是Dart中var變量一旦賦值,不能再改變其類型,如:

var t;
t = "hi world";
// 下面代碼在dart中會報錯,因爲變量t的類型已經確定爲String,
t = 1000;

2、finalconst

常量聲明用 final 或 const 修飾符。常量只能賦值置一次。兩者區別在於:const 變量是一個編譯時常量,final變量在第一次使用時被初始化。被final或者const修飾的變量,變量類型可以省略,如:

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

3、dynamicObject

Object 是Dart所有對象的根基類,也就是說所有類型都是Object的子類(包括Function和Null),所以任何類型的數據都可以賦值給Object聲明的對象。 dynamicvar一樣都是關鍵詞,聲明的變量可以賦值任意對象。 而dynamicObject相同之處在於,他們聲明的變量可以在後期改變賦值類型

 dynamic t;
 Object x;
 t = "hi world";
 x = 'Hello Object';
 //下面代碼沒有問題
 t = 1000;
 x = 1000;

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

 dynamic a;
 Object b;
 main() {
     a = "";
     b = "";
     printLengths();
 }   

 printLengths() {
     // no warning
     print(a.length);

     // warning:The getter 'length' is not defined for the class 'Object'
     print(b.length);
 }

 

三、函數

Dart是一種真正的面向對象的語言,所以即使是函數也是對象,並且有一個類型Function。也就是說函數可以賦值給變量或作爲參數傳遞給其他函數。

1、帶返回值函數聲明

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 ;

2、函數作爲變量

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

3、函數作爲參數

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;
}

下面是一個不帶可選參數調用這個函數的例子:

say('Bob', 'Howdy'); //結果是: Bob says Howdy

下面是用第三個參數調用這個函數的例子:

say('Bob', 'Howdy', 'smoke signal'); //結果是:Bob says Howdy with a smoke signal

可選的命名參數

定義函數時,使用{param1, param2, …},用於指定命名參數。例如:

//設置[bold]和[hidden]標誌
void enableFlags({bool bold, bool hidden}) {
    // ... 
}

調用函數時,可以使用指定命名參數。例如:paramName: value

enableFlags(bold: true, hidden: false);

可選命名參數在Flutter中使用非常多。

結束。謝謝!


參考 https://book.flutterchina.club/chapter1/dart.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章