Dart快速學習之路(完整版)

目錄

前言:

一、Dart介紹 Win Mac上面分別搭建Dart環境  開發工具配置 以及運行Dart

1.1、Dart介紹:

1.2、Dart環境搭建 

1.2.1、 Windows:

1.2.2、 Mac:

1.3、dart 開發環境安裝

1.4、Hello Dart 運行

二、Dart中的變量

2.1、變量定義

2.2 、變量命名規則

2.3、 dart 變量與常量

三、Dart運算符 條件表達式 類型轉換

3.1、運算符

3.1.1、算術運算符

3.1.2、關係運算符

3.1.3、邏輯運算符

3.1.4、賦值運算符

3.2、條件表達式

3.3、數據類型轉換

四、循環語句 for while do...while  break continue 多維列表循環

4.1、++ --運算符

4.2、for循環以及遍歷list

4.3、while和do while循環

4.4、break 和continue

五、集合詳解

5.1、List

5.2、Set

5.3、Map

5.4 遍歷

六、函數

6.1、函數的定義及基本使用

6.2、函數參數介紹

6.2.1、基本參數

6.2.2、可選參數

6.2.3、默認參數

6.2.4、命名參數

6.2.5、參數是函數的函數

6.3、箭頭函數

6.4、函數的相互調用

6.5、匿名方法

6.6、自執行方法

6.7、遞歸函數

6.8、閉包

七、類

7.1、面向對象介紹以及Dart中的內置類

7.2、創建類和使用類

7.3、自定義類的默認構造函數、

7.4、自定義類的命名構造函數

7.5、抽類單獨抽離出來模塊

7.6、類中的私有方法和私有屬性

7.7、類的getter和setter修飾符的用法

7.8、 類的初始化列表

7.9、類的靜態成員和方法

7.10、類的繼承

7.10.1、簡單繼承

7.10.2、super關鍵字

7.10.3、重寫父類方法

7.11、對象操作符

7.12、抽象類

7.13、多態

7.14、接口

7.15、實現多個接口

7.16、mixins 實現多繼承

7.16.1、mixins介紹

7.16.2、mixins的類型

八、泛型

8.1、泛型方法

8.2、泛型類

8.3、泛型接口

九、Dart中的lib介紹

9.1、簡單介紹

9.2、自定義庫

9.3、導入系統內置庫

9.3.1、簡單使用

9.3.2、請求網絡

9.3.3、async 和 await

9.4、導入第三方庫(pub管理包中的庫)

9.5、Dart中的衝突解決

9.6、部分導入

9.7、延遲加載


前言:

此文章只適合有編程基礎的觀看,只介紹dart中比較特殊的部分,謝謝

一、Dart介紹 Win Mac上面分別搭建Dart環境  開發工具配置 以及運行Dart

1.1、Dart介紹:

 Dart是由谷歌開發的計算機編程語言,它可以被用於web、服務器、移動應用 和物聯網等領域的開發。

Dart誕生於2011年,號稱要取代JavaScript。但是過去的幾年中一直不溫不火。直到Flutter的出現現在被人們重新重視。

 要學Flutter的話我們必須首先得會Dart。

 官網:https://dart.dev/

1.2、Dart環境搭建 

要在我們本地開發Dart程序的話首先需要安裝Dart Sdk

  官方文檔:https://dart.dev/get-dart

1.2.1、 Windows:


因爲我這裏已經安裝了,所以我就不演示了

下載後不會的就一直next 就可以,懂點技術的就自己改個你喜歡的安裝目錄

安裝完畢後,在控制檯打開cmd,輸入

dart --version

如果可以看到dart的安裝版本就表示你在windows上安裝成功

1.2.2、 Mac:

輸入如下兩個命令

brew tap dart-lang/dart
        
brew install dart

如果mac電腦沒有安裝brew這個工具首先第一步需要安裝它:  https://brew.sh/

輸入如下命令即可安裝

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

1.3、dart 開發環境安裝

dart安裝成功之後,那麼我們就可以安裝開發環境

Dart的開發工具有很多: IntelliJ IDEA  、 WebStorm、 Atom、Vscode等

這裏我們主要給大家講解的是如果在Vscode中配置Dart。

VS Code 官方 : https://code.visualstudio.com/

因爲我這裏也是已經安裝完了,所以就不演示了,下載完成後一直next即可,或者更改一個你喜歡的安裝目錄再去安裝。

打開VS code,如果我們想要有dart提示,需要安裝一個dart插件:

如果我們想要運行dart 還得安裝 Code Runner 插件,同樣的在上面輸入dart的地方搜索Code Runner

這樣我們就可以在VS Code裏面運行Dart,

注意:因爲Dart 安裝時會自動在系統生成一個SDK環境變量,並加入Path,使得我們在電腦任意位置可以使用,所以執行完上的操作需要重啓下,以便環境變量生效。

1.4、Hello Dart 運行

Java語言文件名後綴以.java爲文件後最,c++以cpp爲文件後綴,同樣,Dart 語言 以 .dart 爲文件後綴,

首先我們選擇一個文件夾用作我們編寫dart的代碼目錄,點擊 Open Folder 選擇一個你喜歡的文件夾

接下來我們就可以在選擇的文件夾中創建dart 文件:

點擊New File,然後輸入你喜歡的文件名,以.dart爲後綴

跟Java語言一樣,Dart也是以main函數爲入口,接着我們通過print 函數打印 hello dart

main(){

  print('hello dart');

 
}

 如下右鍵 點擊Run Code 運行 代碼,右下爲輸出臺,看到 hello dart 輸出

如果你第一次運行出現了亂碼,可以參考這篇文章:https://blog.csdn.net/u010351267/article/details/87865318

————————————————————————————————————————————————————

二、Dart中的變量

2.1、變量定義

void main(){
  /***
   * 
   * dart是一個強大的腳本類語言,可以不預先定義變量類型 ,自動會類型推倒
   * dart中定義變量可以通過var關鍵字可以通過類型來申明變量
   * 如:
   */

//1 String
  var str="你好 dart,我是var";
  print(str);
  String str1=""" 
  this str
  this str1234
  """;
  print(str1);
  //字符串拼接
  String str2="this is str2";
  String str3="this is str3";
  String str4="$str2 $str3";
  String str5=str2+" "+str3;
  print(str4);
  print(str5);

//2 數字類型
  var int_a=110;
  print(int_a);
 //int 必須是整形
  int a=111;
  // int a=11.1;//錯誤
  print(a);
  //3 double既可以是整形也可以是浮點型
  double b=12.5;
  double c=12;
  print(b);
  print(c);
  // 運算符
  double d=b+c;
  print(d);

  //4 布爾類型
  bool flag1=false;
  bool flag2=true;
  print("$flag1,$flag2");

  //5 判斷語句
  if(flag1){
    print("flag1 is true");
  }
  var a1=123;
  var b1="123";
  if(a1==b1){
    print("a1==b1");
  }else{
    print("a1!=b1");
  }

  //6 List
//第一種定義List的方式
  var l1=["aaa","bbb","ccc"];
  print(l1);
  print(l1.length);
  print(l1[2]);
  //第二種方式
  var l2=new List();
  l2.add("ddd");
  l2.add("eee");
  l2.add("fff");
  print(l2[2]);
  //指定List元素的類型
  var l3=new List<int>();
  // l3.add("111");//錯誤
  l3.add(111);

  //7 Map
  var person={
    "name":"張三",
    "age":20
  };
  print(person);
  print(person["name"]);
  print(person["age"]);
  //第二種方式
  var p=new Map();
  p["name"]="李四";
  p["age"]=1123;
  print(p["name"]);

  //8 Dart 判斷數據類型 is 關鍵字
  var var1=12333;
  if(var1 is String){
    print("var1 is String");
  }else if(var1 is int){
    print("var is int");
  }else{
    print("var is other type");
  }


}

注意,dart 有類型檢驗,類型一旦確定,String類型不能轉成int ,int 不能轉換成String,以此類推

/**
 *  注意:
 * 1. var 後就不要寫類型 ,寫了類型 不要var
 * 2. dart 裏面有類型校驗
 */
// var  a int  = 5;   //錯誤

  var str_2="";
  // str_2=1111111; //錯誤
  // int myNum="1111111"; //錯誤

/*

2.2 、變量命名規則

/*

Dart的命名規則:

  1、變量名稱必須由數字、字母、下劃線和美元符($)組成。

  2.注意:標識符開頭不能是數字

  3.標識符不能是保留字和關鍵字。   

  4.變量的名字是區分大小寫的如: age和Age是不同的變量。在實際的運用中,也建議,不要用一個單詞大小寫區分兩個變量。

  5、標識符(變量名稱)一定要見名思意 :變量名稱建議用名詞,方法名稱建議用動詞  
*/
// var 2str="" //錯誤
//var switch="111"; //錯誤
//變量的名字是區分大小寫的如: age和Age是不同的變量
var age=1;
var Age=2;

2.3、 dart 變量與常量

變量定義後,還可以更改:

void main(){
  //變量
  var str_3="I am var str";
  str_3="我是var字符串";
  int int_3=1233;
  int_3=4444;
  print(str_3);
  print(int_3);
}

在dart 中 常量可以用 const 和 final 關鍵字修飾:

/*
const值不變 一開始就得賦值
final 可以開始不賦值 只能賦一次 ; 而final不僅有const的編譯時常量的特性,
最重要的它是運行時常量,並且final是惰性初始化,即在運行時第一次使用前才初始化
永遠不改量的量,請使用final或const修飾它,而不是使用var或其他變量類型。
    */
//const 常量
const const_1=100;
//Constant variables can't be assigned a value.
//const_1=101; //錯誤,const修飾的常量不可以修改

final final_1=110;
//Constant variables can't be assigned a value.
//final_1=111;//錯誤,const修飾的常量不可以修改

final currentTime_final=new DateTime.now();
print(currentTime_final);
//Const variables must be initialized with a constant value.
//const currentTime_const=new DateTime.now();//錯誤

 

三、Dart運算符 條件表達式 類型轉換

3.1、運算符

3.1.1、算術運算符

void main(){
  int a=13;
  int b=5;
  print(a+b);
  print(a-b);
  print(a*b);
  print(a/b);
  print(a%b);
  print(a~/b);


  var c=a*b;
  print("------------");
  print(c);
}

3.1.2、關係運算符

void main(){
  // == !+ < > <= >=
  int a=5;
  int b=3;
  print(a==b);
  print(a!=b);
  print(a>b);
  print(a<b);
  print(a>=b);
  print(a<=b);

  if(a>b){
    print("a>b");
  }else{
    print("a<b");
  }

}

3.1.3、邏輯運算符

void main(){

  /** ! 取反 */
  bool flag=false;
  print(!flag);

  /**&& 並且:全部爲true的話值爲true 否則值爲false */
  bool a=true;
  bool b=false;
  print(a&&b);


  /**|| 或者:全爲false的話值爲false,否則爲true */
  print(a||b);

  //如果這個東西的重量大於5,並且體積大於10 執行 打印true,否認打印false。
  int weight=6;
  int bulk=11;
  if(weight>5 && bulk>10){
    print("true &&");
  }else{
    print("false &&");
  }

  //如果這個東西的重量大於5,或者體積大於10 執行 打印true,否認打印false。
  if(weight>5 || bulk>10){
    print("true ||");
  }else{
    print("false ||");
  }

}

3.1.4、賦值運算符

void main(){
  //1、基礎賦值運算符 + ??=
  int a=10;
  int b=3;
  print(a);

  int c=a+b; //從右向左
  print("$c");

  //??= 表示左邊如果爲空,將右邊賦值給左邊
  c??=22;
  print("$c");
  int d;
  d??=22;
  print("$d");

  //2、複合賦值運算符 += -= *= /= %= ~/=
  var e=23;
  e+=10;//表示e=e+10;
  print("$e");


}

這裏值得提一下的是 ?? 表示判斷左邊的變量是否爲空。

3.2、條件表達式

void main(){
    //1、if else switch case
    bool flag=true;
    if(flag){
      print("if true");
    }else{
      print("if false");
    }

    //判斷一個人的體重小於50kg就是偏廋,大於80kg就是偏重,否則是正常
    var weight=60;
    if(weight<50){
      print("小於50偏廋");
    }else if(weight>80){
      print("大於80偏重");
    }else{
      print("正常體重");
    }

//switch
    var season="夏天";
    switch(season){
      case "冬天":
        print("我是冬天");
          break;
      case "春天":
        print("我是春天");
          break;
      case "夏天":
        print("我是夏天");
          break;
      case "球天":
        print("我是秋天");
          break;
      default:
        print("我啥也不是");
          break;
    }

    //三目運算符
    print(flag?"我是flag:$flag":"我啥也不是flag");

    //?? 運算符
    var c;
    //如果c沒有定義則10賦值給c2.
    var c2=c ?? 10;
    print("??運算符 $c2");
  
}

3.3、數據類型轉換

void main(List<String> args) {
  //1、Number與String類型之間的轉換。
  String str="110";
  var myNum=int.parse(str);
  print(myNum is int);
  /**
   *   錯誤
   *  String str1="110.1";
   *  var myNum1=int.parse(str1);
      Unhandled exception:
      FormatException: Invalid radix-10 number (at character 1)
   */

  //鑑於上面的錯誤,所以我們建議使用double
  //,這樣即可處理整型也可以處理浮點型
  String str2="1111";
  String str3="1113";
  var d1=double.parse(str2);
  var d2=double.parse(str3);
  print(d1 is int);
  print(d2 is int);

  

  //加入出現了上面的錯誤,我們可以用try catch捕獲錯誤。
  try{
    String str1="110.1";
    var myNum1=int.parse(str1);
  }catch(err){
    print("我沒有崩潰哦,我是主人的小助手");
  }

  var num1=12;
  String str4=num1.toString();
  print(str4 is String);
 
 //booleans的轉換
  //判斷字符串是否爲空
  String str5="我是 str5 哦";
  if(str5.isEmpty){
    print("我不爲空,我是str5");
  }else{
    print("我啥也沒有嗚嗚嗚");
  }

  //特殊
  var a=0/0;
  print(a);//打印出Nan,不會報錯
  if(a.isNaN){
    print("我是Nan,被除數爲0");
  }


}

這裏需要注意的是Dart中0可以作爲被除數,不會報錯,並且打印出Nan,可以用此判斷是否是被除數爲0.

 

四、循環語句 for while do...while  break continue 多維列表循環

4.1、++ --運算符

//++ --
  void main(){
    var a=10;
    a++;//a=a+1;
    print(a);

    var b=10;
    b--;//b=b-1;
    print(b);

//在賦值運算裏面,如果++ -- 寫在前面,這時候先運算
//如果++ --寫在後面,先賦值後運算。
    var c=10;
    var c2=10;
    var c3=10;
    var c4=10;
    var d=c--;
    var d2=--c2;
    var d3=c3++;
    var d4=++c4;
    
    print("c=$c");
    print("c2=$c2");
    print("c3=$c3");
    print("c4=$c4");
    print("d=$d");
    print("d2=$d2");
    print("d3=$d3");
    print("d4=$d4");
  }

這裏需要注意的就是:

  1. 如果++ -- 寫在前面,這時候先運算
  2. 如果++ --寫在後面,先賦值後運算。

4.2、for循環以及遍歷list

void main(){

  for(int i=0;i<10;i++){
      print(i);
  }

  //打印小於50 的偶數
  for(int i=0;i<50;i++){
    if(i%2==0){
      print(i);
    }
  }

  //打印5的階層
  int sum=1;
  for(int i=1;i<=5;i++){
    sum*=i;
  }
  print(sum);

  //打印List ["小紅","小張","小明"]
  List list1=["小紅","小張","小明"];
  for(int i=0;i<list1.length;i++){
    print(list1[i]);
  }

  List list2=[{"title":"疫情1"},
  {"title":"疫情2"},
  {"title":"疫情3"},];
  for(int i=0;i<list2.length;i++){
    print(list2[i]["title"]);
  }

  //定義二維數組打印裏面的內容
  List list3=[
    {
      "cate":"國內",
      "news":[
        {"title":"疫情國內1"},
        {"title":"疫情國內2"},
        {"title":"疫情國內3"},
      ]
    },

     {
      "cate":"國外",
      "news":[
        {"title":"疫情國外1"},
        {"title":"疫情國外2"},
        {"title":"疫情國外3"},
      ]

    }

  ];
  for(int i=0;i<list3.length;i++){
    print(list3[i]["cate"]);
    for(int j=0;j<list3[i]["news"].length;j++){
       print(list3[i]["news"][j]["title"]);
    }
  }

}

這裏看出來和java中的for循環沒有區別,注意的就是多維list遍歷的情況

4.3、while和do while循環

/*
格式語法:

while是先判斷條件,do while是先執行循環體

 while(表達式/循環條件){
   語句/循環體
 }

 do{
   語句/循環體
 }while(表達式/循環條件);

注意:
1.最後的分號不要忘記
2.循環條件中使用的變量經過初始化
3.循環體中,應有結束循環的條件,否則會造成死循環。
 */
void main(){

  int a = 0;
  while(a<10){
    print("while a=$a");
    a++;
  }

  a=0;
  do {
    print("dowhile a=$a");
    a++;
  } while (a<10);

  //求1+2+3+....+100的和
  int a1=1;
  int sum=0;
  while(a1<=100){
    sum+=a1;
    a1++;
  }
   print("while sum=$sum");
  a1=1;
  sum=0;
  do {
    sum+=a1;
    a1++;
  } while (a1<=100);
  print("dowhile sum=$sum");

  //while 和do while區別
  int a2=1;
  while(a2>2){
    print("while....");
  }

  do {
    print("do while....");
  } while (a2>2);

}

這裏可以看出和java也是沒有區別,值得再次提出的就是while和do while的區別:
do while是先執行循環體,再執行判斷條件,而while是執行判斷條件,如果判斷條件不成立,則結束循環。

4.4、break 和continue

/*
break語句功能:
  1.在switch語句中使流程跳出switch 結構
  2.在循環語句中使流程跳出當前循環,遇到break循環終止,後面代碼也不會執行

  強調:
    1.如果在循環中已經執行了break語句,就不會執行循環體中位於break後的語句。
    2.在多層循環中,一個break語句只能向外跳出一層

    break可以用在switch case中,也可以用在for循環和while循環中。

    continue語句的功能:
    【注】只能在循環語句中使用,使本次循環結束,即跳過循環體重=下面尚未執行的語句,接着進行下次的是否執行循環的判斷。
     continue可以用在for循環以及 while循環中,但是不建議用在while循環中,不小心容易死循環
*/

void main(){
  //continue跳過i =4的值
  for(int i=0;i<10;i++){
    if(i==4){
      continue;
    }
    print("i=$i");
  }

  //break退出當前層循環
  for(int i=0;i<1;i++){
    for(int j=0;j<10;j++){
      if(j==4){ 
        break;
      }
      print("j====$j");
    }
    print("i====$i");
  }     

  var sex="男";
  switch(sex){
    case "男":
      print("男上加男");
      break;
    case "女":
      print("女");
      break;
  }

  int w=1;
  while(w<10){
    if(w==4){
        break;
    }
    print("w===$w");
    w++;
  }

}

這裏可以看到和java沒有區別,非常簡單。

五、集合詳解

5.1、List

void main(){
  //定義1
  List myList=["香蕉","蘋果","西瓜"];
  print(myList[0]);

  //定義2
  var myListVar=new List();
  myListVar.add("111");
  myListVar.add("222");
  print(myListVar);

  //List裏面的屬性
  List list1=["香蕉","蘋果","西瓜"];
  print(list1.length);
  print(list1.isEmpty);
  print(list1.isNotEmpty);
  print(list1.reversed);//對列表倒序排序

  var list2=list1.reversed.toList();
  print(list2);

  //list裏面的方法
  //1 增加數據
  List list3=["香蕉","蘋果","西瓜"];
  list3.add("哈密瓜");//增加單個數據
  print(list3);
  list3.addAll(myListVar);//增加集合
  print(list3);
  print(list3.indexOf("11111"));//查找指定數據索引,有的話返回索引,沒有返回-1

//刪除數據
  list3.remove("哈密瓜");//刪除指定數據
  print(list3);
  list3.removeAt(1);//刪除指定下標數據
  print(list3);

//替換數據
  list3.fillRange(0, 1,"----");//替換指定範圍索引的數據,包含頭,不包含尾。
  print(list3);

//插入數據
  list3.insert(1, "========");//在指定索引插入單個數據
  print(list3);
  list3.insertAll(2,myListVar);//在指定索引插入多個數據
  print(list3);


  List list4=["香蕉","蘋果","西瓜"];
  var str=list4.join("--");//將List轉換爲字符串
  print(str);
  print(str is String);

  var str1="小明-小紅-小王";
  var list5=str1.split("-");
  print(list5);
  print(list5 is List);

}

沒有太大難度,基本跟Java一摸一樣

5.2、Set

/*
Set是沒有順序且不能重複的集合,所以不能通過索引去獲取值
*/
void main(){
  var s=new Set();
  s.add("校長");
  s.add("老師");
  s.add("主任");
  s.add("主任");
  print(s);

  print(s.toList());

  List list1=["香蕉","蘋果","西瓜","香蕉",
  "蘋果","西瓜","香蕉","蘋果","西瓜"];
  var s1=new Set();
  s1.addAll(list1);
  print(s1);
  print(s1.toList());


}

5.3、Map

/*
Map是無序的鍵值對
*/
void main(){
  var person={
    "name":"小明",
    "age":20,
  };

  var map1=new Map();
  map1["name"]="小紅";
  print(person);
  print(map1);

  //常用屬性
  print(person.keys);//打印所有的key
  print(person.values);//打印所有的value
  print(person.isNotEmpty);
  print(person.isEmpty);

  //常用方法
  //增加數據
  person.addAll({
    "work":["敲代碼","送外賣"],
    "height":"160"
  });
  print(person);

//刪除
  person.remove("height");
  print(person);

//是否包含某個key
  print(person.containsKey("work"));

}

5.4 遍歷

void main(){
  List persons=["夏紅","下雨","下冰雹"];
  for(int i=0;i<persons.length;i++){
    print(persons[i]);
  }

  for(var item in persons){
    print(item);
  }

  persons.forEach((key){
    print("key=$key");
  });

//遍歷list,並將裏面的數據統一處理*2,返回一個新的List
  List list2=[11,22,33];
  var list3=list2.map((value){
    return value*2;
  });
  print(list3);

//返回指定條件的數據,返回一個新的List
  var list4=list2.where((value){
    return value==11;
  });
  print(list4);

//判斷List裏面是否有滿足該條件的數據,如果有返回true,否則false
  List myList=[11,22,33];
  var flag=myList.any((value){
    return value>1;
  });
  print(flag);

//判斷List裏面是否是全部滿足該條件的數據,如果是返回true,否則false
  var flag2=myList.every((value){
    return value>20;
  });
  print(flag2);

  //Set
  var set1=new Set();
  set1.add([111,222,33]);
  set1.forEach(
    (value)=>print(value)//一行代碼的簡寫
  );

  //map
  Map persons2={
    "name":"張山",
    "age":222
  };
  persons2.forEach((key,value){
    print("key=$key,value=$value");
  });



}

六、函數

6.1、函數的定義及基本使用

/*
內置方法函數:
print();

方法的基本格式:
返回類型 方法名稱(參數1,參數2....){
  方法體
  return 返回值;
}
*/

void test(){
  print("我是test 函數");
  //當返回值爲空或者不確定可以省略,最好是明確寫清楚
  test2(){
    print("我是test2 函數");
  }
  test2();
}

List getList(){
  return ["111","222","333"];
}


//入口函數
void main(){
  print("我是 main函數");
  test();
  //錯誤,test中的test2作用域只能在test.
  //test2();

//函數內部定義函數,只能在main函數中調用
  int getNum(){
    print("我是getNum函數");
    return 110;
  }

  print(getNum());

  print(getList());
  //多次調用同一個函數
  print(getList());

}

這裏需要注意是的是與java不同,dart函數內部還可以定義函數,並且返回值類型和參數類型可以不明確,但是最好明確,以免出現不必要的問題

6.2、函數參數介紹

6.2.1、基本參數

//1.定義一個方法,求1到這個數的所有數的和
getSum(maxValue){//參數類型可以省略,但最好寫清楚,以免瞎傳參
  var sum=0;
  for(var i=1;i<=maxValue;i++){
    sum+=i;
  }
  return sum;
}

void main(){
//調用有參數的方法
  print(getSum(50));
}

6.2.2、可選參數

//可選參數,可選參數後面的參數都需要是可選參數
String getPersonInfo(String name,[int age,String sex]){
  if(age!=null){
    return "getPersonInfo name=$name,age=$age";
  }
  return "getPersonInfo name=$name,age unknow";
}

void main(){
  print(getPersonInfo("小明"));
  print(getPersonInfo("小明",20));
}

可選參數用[]中括號括起來,可選參數後面的參數都需要是可選參數

6.2.3、默認參數

//默認參數
String getPersonInfo2(String name,[String sex="男",int age]){
  if(age!=null){
    return "getPersonInfo2 name=$name,age=$age,sex=$sex";
  }
  return "getPersonInfo2 name=$name,age unknow,,sex=$sex";
}

void main(){
//使用默認參數
  print(getPersonInfo2("小李"));
  //覆蓋默認參數sex
  print(getPersonInfo2("小李","女"));
  print(getPersonInfo2("小李","女",22));
}

默認參數如果不傳入則使用默認,如果傳入則覆蓋,並且只能在[]中括號,或者{}大括號裏面定義

6.2.4、命名參數

//定義一個命名參數的方法
String getPersonInfo3(String name,{String sex="男",int age}){
  if(age!=null){
    return "getPersonInfo3 name=$name,age=$age,sex=$sex";
  }
  return "getPersonInfo3 name=$name,age unknow,,sex=$sex";
}

void main(){
    print(getPersonInfo3("小紅",sex:"女"));
}

命名參數必須定義在{}打括號裏面,注意不是[]中括號、

6.2.5、參數是函數的函數

//把一個方法當作參數
fun1(){
  print("fun1------");
}
fun2(fun){
  fun();
}
void main(){
  //調用參數是函數的方法
  fun2(fun1);
}

注意:在dart中,當參數是一個函數時,只需要將函數名字傳入,並不需要寫() 小括號。

6.3、箭頭函數

List list=["小紅","校長","feig"];
list.forEach((value){
    print("value=$value");
  });

  //箭頭函數 1
  //注意箭頭函數只能有一條語句
  list.forEach((value)=>print("value=$value"));

  //2
  list.forEach((value)=>{
      print("value=$value")//注意這裏不用寫分號;
  });

  //修改下面List裏面的數據,讓數組中大於2的值乘以2
  List list2=[1,2,3,3];
  var newList1=list2.map((value){
    if(value>2){
      return value*2;
    }
    return value;
  });
  print(newList1.toList());
  var newList2=list2.map((value)=>value>2?value*2:value );
  print(newList2.toList());

需要注意箭頭函數只能有一條語句

6.4、函數的相互調用

void main(){
  /*
  1.定義一個方法isEvenNumber來判斷一個數是否是偶數
  2.定義一個方法打印1-n以內的所有偶數
  */
  bool isEvenNumber(int n){
    if(n%2==0){
      return true;
    }
    return false;
  }

  printNum(int n){
    for(int i=1;i<=n;i++){
      if(isEvenNumber(i)){
        print(i);
      }

    }
  }
  printNum(10);
}

6.5、匿名方法

void main(){
  //匿名函數
  //不帶參數
  var printNum=(){
    print("123");
  };
  printNum();
  //帶參數
  var printNum2=(int i){
    print(i);
  };
  printNum2(321);
}

6.6、自執行方法

void main(){
//自執行方法
  ((){
  print("我是自執行方法");
  })();

  ((int n){
  print("我是自執行方法 n=$n");
  })(11);

}

6.7、遞歸函數

void main(){
    //方法的遞歸
  var sum=1;
  fn(n){
    sum*=n;
    if(n==1){ 
      return;
    }
    fn(n-1);
  }

  fn(5);
  print("sum=$sum");
  sum=0;

  //通過方法遞歸,求1-100的和
  fn1(int n){
    sum+=n;
    if(n==0){
      return;
    }
    fn1(n-1);
  }
  fn1(100);
  print("sum100=$sum");
}

遞歸要注意的就是返回條件,避免死循環。

6.8、閉包

/*
閉包:
1.全局變量特點:全局變量常駐內存、全局變量污染全局
2.局部變量的特點:不常駐內存會被垃圾機制回收,不會污染全局

想實現的功能:
1.常駐內存
2.不污染內存
產生了閉包,閉包可以解決這個問題
閉包:函數嵌套函數,內部函數會調用外部函數的變量或參數,
變量或參數不會被系統回收(不會釋放內存)

閉包的寫法:函數嵌套函數,並return 裏面的函數,這樣就形成了閉包
*/
void main(){
  //閉包
  fun(){
    var a=123;
    return(){
      a++;
      print(a);
    };
  }

  var b=fun();
  b();//124
  b();//125
  b();//126
}

七、類

7.1、面向對象介紹以及Dart中的內置類

/*

面向對象編程(OOP)的三個基本特徵是:封裝、繼承、多態      

      封裝:封裝是對象和類概念的主要特性。封裝,把客觀事物封裝成抽象的類,並且把自己的部分屬性和方法提供給其他對象調用, 而一部分屬性和方法則隱藏。
                
      繼承:面向對象編程 (OOP) 語言的一個主要功能就是“繼承”。繼承是指這樣一種能力:它可以使用現有類的功能,並在無需重新編寫原來的類的情況下對這些功能進行擴展。
            
      多態:允許將子類類型的指針賦值給父類類型的指針, 同一個函數調用會有不同的執行效果 。


Dart所有的東西都是對象,所有的對象都繼承自Object類。

Dart是一門使用類和單繼承的面嚮對象語言,所有的對象都是類的實例,並且所有的類都是Object的子類

一個類通常由屬性和方法組成。

*/
void main(){
  List list=new List();
  list.isEmpty;
  list.add("你好");
  list.add("hello");

  Map map=new Map();
  map["name"]="張三";
  map.addAll({"age":12});
  map.isEmpty;

}

和java基本沒區別

7.2、創建類和使用類

class Person{
  int age=20;
  String name="夏利";

  void getInfo(){
    print("getInfo age=$age,name=$name");
  }
  void getInfo2(){
    print("getInfo2 age=${this.age},name=${this.name}");
  }
  void setAge(int age){
    this.age=age;
  }
  int getAge(){
    return this.age;
  }
  void setName(String name){
    this.name=name;
  }
  String getName(){
    return this.getName();
  }

}

void main(){
  var p=new Person();
  Person p1=new Person();
  print("main age=${p.age},name=${p.name}");
  p.getInfo2();
  p1.getInfo();
  p1.getInfo2();

  Person p2=new Person();
  p2.setAge(111);
  p2.getInfo();

}

7.3、自定義類的默認構造函數、

class Person{
  int age=20;
  String name="夏利";

  void getInfo(){
    print("getInfo age=$age,name=$name");
  }

//無參構造函數,構造函數只能有一個
  Person(){
    print("=======Person Start=======");
    getInfo();
    print("=======Person stop=======");
  }

}

class SupperPerson{
  int age=20;
  String name="夏利";

  void getInfo(){
    print("getInfo age=$age,name=$name");
  }

//有參數構造函數
  SupperPerson(int age,String name){
    this.age=age;
    this.name=name;
    print("=======SupperPerson Start=======");
    getInfo();
    print("=======SupperPerson stop=======");
  }

}

class MaxPerson{
  int age=20;
  String name="夏利";

  void getInfo(){
    print("getInfo age=$age,name=$name");
  }

//構造函數,簡寫
  MaxPerson(this.age,this. name){
    getInfo();
  }

}
void main(){
  Person p=new Person();
  SupperPerson sp=new SupperPerson(18, "Fay");
  MaxPerson mp=new MaxPerson(19, "wt");
}

7.4、自定義類的命名構造函數

class Person{
  int age=20;
  String name="夏利";

  void getInfo(){
    print("getInfo age=$age,name=$name");
  }

  Person(int age,String name){
    this.age=age;
    this.name=name;
    getInfo();
  }

  Person.now(){
    print("我是命名構造函數");
  }

//命名構造函數可以有多個
  Person.getAge(){
    print("getAge age=$age");
  }

  Person.setAge(this.age){
    print("setAge age=$age");
  }

}


void main(){
  Person p=new Person(16,"Fay");
  Person p1=new Person.now();
  Person p2=new Person.getAge();
  Person p3=new Person.setAge(18);
}

7.5、抽類單獨抽離出來模塊

bean/Person.dart

class Person{
  int age=20;
  String name="夏利";

  void getInfo(){
    print("getInfo age=$age,name=$name");
  }

  Person(int age,String name){
    this.age=age;
    this.name=name;
    getInfo();
  }

  Person.now(){
    print("我是命名構造函數");
  }

//命名構造函數可以有多個
  Person.getAge(){
    print("getAge age=$age");
  }

  Person.setAge(this.age){
    print("setAge age=$age");
  }

}

main.dart

import 'bean/Person.dart';
void main(){
  Person p=new Person.setAge(18);
}

通過import去引用其他模塊文件的類

7.6、類中的私有方法和私有屬性

bean/Animal.dart

class Animal{
  //通過下劃線表示私有
  int _age=2;
  String name="貓";

  void _getInfo(){
    print("getInfo age=$_age,name=$name");
  }

  void execGetInfo(){
    this._getInfo();//類中的方法相互調用
  }

  void setAge(int age){
    this._age=age;
  }

  int getAge(){
    return this._age;
  }

  Animal(int age,String name){
    this._age=age;
    this.name=name;
    _getInfo();
  }

}

main.dart 

/*
Dart和其他面嚮對象語言不一樣,Data中沒有 public  private protected這些訪問修飾符合

但是我們可以使用_把一個屬性或者方法定義成私有。

Dart中的私有屬性必須在單獨的模塊文件,並且在前面加上_下劃線
*/

import 'bean/Animal.dart';

void main(){
  Animal animal=new Animal(2,"dog");
  print(animal.name);
  //print(animal._age)//錯誤,無法訪問屬性
  print("getAge:${animal.getAge()}");//通過公有方法訪問私有屬性
  // animal.getInfo();//錯誤,無法訪問私有方法
  animal.execGetInfo();//通過共有方法訪問私有方法

}

Dart中的私有屬性必須在單獨的模塊文件,並且在前面加上_下劃線,通過共有方法去訪問私有屬性和私有方法。

7.7、類的getter和setter修飾符的用法

bean/Rect.dart

class Rect{
  int width;
  int height;
  Rect(this.width,this.height);
  area(){
    return this.height*this.width;
  }
  get area2get{
    return this.height*this.width*2;
  }

  set setHeight(value){
    this.height=value;
  }
}

 main.dart

import 'bean/Rect.dart';
void main(){
  Rect r=new Rect(5,10);
  print("area=${r.area()}");
  print("area=${r.area2get}");//直接通過屬性的方式訪問area2get.

  r.setHeight=30;//直接通過屬性的方式訪問setHeight.
  print("===area=${r.area()}");

}

7.8、 類的初始化列表

class Rect{
  int width;
  int height;
  Rect():height=1,width=1{
    print("Rect height=$height,width=$width");
  }
  area(){
    return this.height*this.width;
  }
 
}
void main(){
  Rect r=new Rect();
}

通過:冒號表示,多個初始化通過,逗號分隔

7.9、類的靜態成員和方法

/*
Dart中的靜態成員:
1.使用static關鍵字來實現類級別的變量和函數
2.靜態方法不能訪問非靜態成員,非靜態方法可以訪問靜態成員
*/

class Person{
  static String name="張三";
  int age=18;
  static void show(){
    /*
    Instance members can't be accessed from a static method.
    靜態方法show不能訪問非靜態成員age
    靜態方法show不能訪問非靜態方法printInfo2
    */
    // printInfo2();//錯誤
    //print(name+",age=$age");//錯誤
    print(name);
    printInfo3();
  }
  void printInfo(){
    //非靜態方法可以訪問靜態成員
    print(name+",age=$age");
    show();
    printInfo2();
  }
  void printInfo2(){
    print("printInfo2");
  }
  static void printInfo3(){
    print("printInfo3");
  }
}

void main(){
  Person.show();
  Person p=new Person();
  p.printInfo();
}

7.10、類的繼承

7.10.1、簡單繼承

/*

面向對象的三大特性:封裝 、繼承、多態


Dart中的類的繼承:  
    1、子類使用extends關鍵詞來繼承父類
    2、子類會繼承父類裏面可見的屬性和方法 但是不會繼承構造函數
    3、子類能複寫父類的方法 getter和setter

*/

class Person {
  String name='張三';
  num age=20; 
  void printInfo() {
    print("${this.name}---${this.age}");  
  } 
}
class Web extends Person{

}

main(){   

  Web w=new Web();
  //使用父類的屬性和方法
  print(w.name);
  w.printInfo();
 
}

7.10.2、super關鍵字

class Person {
  String name;
  num age; 
  Person(this.name,this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}


class Web extends Person{
  //定義自己的屬性
  String sex="web";
  //使用super關鍵字重寫父類構造函數
  Web(String name, num age,String sex) : super(name, age){
    this.sex=sex;
  }

  //定義自己的函數
  void getInfo(){
    print("age=$age,name=$name,sex=$sex");
  }
  
}

main(){ 

  Web w=new Web('張三', 12,"webwebweb111");
  //調用父類的方法
  w.printInfo();
  //調用自己的方法
  w.getInfo();


}

7.10.3、重寫父類方法


class Person {
  String name;
  num age; 
  Person(this.name,this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
}


class Web extends Person{
  //定義自己的屬性
  String sex="web";
  //使用super關鍵字調用父類的構造函數,給父類構造函數傳參
  Web(String name, num age,String sex) :super(name,age){
    this.sex=sex;
  }

  //複寫父類的函數
  @override
  void printInfo() {
    print("Web name=$name,age=$age,sex=$sex");
  }


}

void main(){
   Web w=new Web('張三', 12,"bew");
   //因爲複寫了,所以調用的是自己複寫後的方法。
   w.printInfo();
}

7.11、對象操作符

/*
Dart中的對象操作符:

    ?     條件運算符 (瞭解)
    as    類型轉換
    is    類型判斷
    ..    級聯操作 (連綴)  (記住)
*/

import '01類中的靜態成員 靜態方法.dart';

class Person {
  String name;
  num age;
  Person(this.name,this.age);
  void printInfo() {
    print("${this.name}---${this.age}");  
  }
  
}


void main(){
  Person p;
  p?.printInfo();//?判斷p爲空則不調用printInfo()
  p=new Person("Fay",18);
  p.printInfo();

  print(p is Person);//is 判斷p是否是Person對象的實例、

  var p1;
  p1="";
  p1=new Person("wt",23);
  (p1 as Person).printInfo();//as 轉換爲具體對象

  Person p2=new Person("secret",22);
  p2.printInfo();
  p2.name="weight";
  p2.age=110;
  p2.printInfo();
  //練級調用
  p2..name="wight.."
    ..age=111
    ..printInfo();

}

7.12、抽象類

/*
Dart中抽象類: Dart抽象類主要用於定義標準,子類可以繼承抽象類,也可以實現抽象類接口。


  1、抽象類通過abstract 關鍵字來定義

  2、Dart中的抽象方法不能用abstract聲明,Dart中沒有方法體的方法我們稱爲抽象方法。

  3、如果子類繼承抽象類必須得實現裏面的抽象方法

  4、如果把抽象類當做接口實現的話必須得實現抽象類裏面定義的所有屬性和方法。

  5、抽象類不能被實例化,只有繼承它的子類可以

extends抽象類 和 implements的區別:

  1、如果要複用抽象類裏面的方法,並且要用抽象方法約束自類的話我們就用extends繼承抽象類

  2、如果只是把抽象類當做標準的話我們就用implements實現抽象類



案例:定義一個Animal 類要求它的子類必須包含eat方法

*/

abstract class Animal{
  eat();   //抽象方法
  run();  //抽象方法  
  printInfo(){
    print('我是一個抽象類裏面的普通方法');
  }
}

class Dog extends Animal{
  @override
  eat() {
     print('小狗在喫骨頭');
  }

  @override
  run() {
    // TODO: implement run
    print('小狗在跑');
  }  
}
class Cat extends Animal{
  @override
  eat() {
    // TODO: implement eat
    print('小貓在喫老鼠');
  }

  @override
  run() {
    // TODO: implement run
    print('小貓在跑');
  }

}

main(){

  Dog d=new Dog();
  d.eat();
  d.printInfo();

   Cat c=new Cat();
  c.eat();

  c.printInfo();


  // Animal a=new Animal();   //抽象類沒法直接被實例化

}
  1. 和java不同的是 Dart中抽象類 中的方法 不需要用abstract聲明,和java中接口一樣定義方式
  2. 如果使用implements實現抽象類,屬性和方法都必須實現
  3. 抽象方法不能像java 一樣匿名實現定義。

7.13、多態

/*
Datr中的多態:
    允許將子類類型的指針賦值給父類類型的指針, 同一個函數調用會有不同的執行效果 。

    子類的實例賦值給父類的引用。
    
    多態就是父類定義一個方法不去實現,讓繼承他的子類去實現,每個子類有不同的表現。

*/


import '01Dart中的抽象類.dart';

abstract class Animal{
  eat();   //抽象方法 
}

class Dog extends Animal{
  @override
  eat() {
     print('小狗在喫骨頭');
  }
  run(){
    print('run');
  }
}
class Cat extends Animal{
  @override
  eat() {   
    print('小貓在喫老鼠');
  }
  run(){
    print('run');
  }
}

main(){

  // Dog d=new Dog();
  // d.eat();
  // d.run();


  // Cat c=new Cat();
  // c.eat();


  Animal d=new Dog();

  d.eat();

 

  Animal c=new Cat();

  c.eat();

 


}

7.14、接口

/*
和Java一樣,dart也有接口,但是和Java還是有區別的。

  首先,dart的接口沒有interface關鍵字定義接口,而是普通類或抽象類都可以作爲接口被實現。

  同樣使用implements關鍵字進行實現。

  但是dart的接口有點奇怪,如果實現的類是普通類,會將普通類和抽象中的屬性的方法全部需要覆寫一遍。
  
  而因爲抽象類可以定義抽象方法,普通類不可以,所以一般如果要實現像Java接口那樣的方式,一般會使用抽象類。

  建議使用抽象類定義接口。

*/

/*
定義一個DB庫 支持 mysql  mssql  mongodb

mysql  mssql  mongodb三個類裏面都有同樣的方法

*/


abstract class Db{   //當做接口   接口:就是約定 、規範
    String uri;      //數據庫的鏈接地址
    add(String data);
    save();
    delete();
}

class Mysql implements Db{
  
  @override
  String uri;

  Mysql(this.uri);

  @override
  add(data) {
    // TODO: implement add
    print('這是mysql的add方法'+data);
  }

  @override
  delete() {
    // TODO: implement delete
    return null;
  }

  @override
  save() {
    // TODO: implement save
    return null;
  }

  remove(){
      
  }

  
}

class MsSql implements Db{
  @override
  String uri;
  @override
  add(String data) {
    print('這是mssql的add方法'+data);
  }

  @override
  delete() {
    // TODO: implement delete
    return null;
  }

  @override
  save() {
    // TODO: implement save
    return null;
  }


}

main() {

  Mysql mysql=new Mysql('xxxxxx');

  mysql.add('1243214');

  


  
}

Dart中使用抽象類代替了接口,實現抽象類,就必須實現所有的抽象方法和屬性。

7.15、實現多個接口

/*
Dart中一個類實現多個接口:
*/

abstract class A{
  String name;
  printA();
}

abstract class B{
  printB();
}

class C implements A,B{  
  @override
  String name;  
  @override
  printA() {
    print('printA');
  }
  @override
  printB() {
    // TODO: implement printB
    return null;
  }

  
}


void main(){

  C c=new C();
  c.printA();


}

7.16、mixins 實現多繼承

7.16.1、mixins介紹

/*
mixins的中文意思是混入,就是在類中混入其他功能。

在Dart中可以使用mixins實現類似多繼承的功能


因爲mixins使用的條件,隨着Dart版本一直在變,這裏講的是Dart2.x中使用mixins的條件:

  1、作爲mixins的類只能繼承自Object,不能繼承其他類
  2、作爲mixins的類不能有構造函數
  3、一個類可以mixins多個mixins類
  4、mixins絕不是繼承,也不是接口,而是一種全新的特性
*/

class Person{
  String name;
  num age;
  Person(this.name,this.age);
  printInfo(){
    print('${this.name}----${this.age}');
  }
  void run(){
    print("Person Run");
  }
}

class A {
  String info="this is A";
  void printA(){
    print("A");
  }
  void run(){
    print("A Run");
  }
}

class B {  
  void printB(){
    print("B");
  }
  void run(){
    print("B Run");
  }
}

class C extends Person with B,A{
  C(String name, num age) : super(name, age);
  
}

void main(){  
  var c=new C('張三',20);  
  c.printInfo();
  // c.printB();
  // print(c.info);

   c.run();


}









  1. dart中使用mixins實現多繼承,使用with關鍵字
  2. 當繼承的多個類中有同樣的方法時,誰排在最後則調用誰的函數。
  3. 作爲mixins的類只能繼承自Object,不能繼承其他類

  4. 作爲mixins的類不能有構造函數

7.16.2、mixins的類型

/*
mixins的實例類型是什麼?

很簡單,mixins的類型就是其超類的子類型。

*/



class A {
  String info="this is A";
  void printA(){
    print("A");
  }
}

class B {
  void printB(){
    print("B");
  }
}

class C with A,B{
  
}

void main(){  
   var c=new C();  
   
  print(c is C);    //true
  print(c is A);    //true
  print(c is B);   //true


  // var a=new A();

  // print(a is Object);


}

八、泛型

8.1、泛型方法

/*

通俗理解:泛型就是解決 類 接口 方法的複用性、以及對不特定數據類型的支持(類型校驗)

*/

//編寫一個函數,傳入什麼類型怎返回什麼類型
/*
代碼太冗餘
String getDataString(String str){
  return str;
}
int getDataInt(int number){
  return number;
}
*/
//泛型高效方便
T getData<T>(T t){
  return t;
}

void main(){
  print(getData("1111"));
  print(getData(2222));
  //指定類型
  // print(getData<String>(2222));//錯誤
  print(getData<String>("hello world"));
}

8.2、泛型類

//案例:把下面類轉換成泛型類,要求List裏面可以增加int類型的數據,也可以增加String類型的數據。但是每次調用增加的類型要統一
/*
只能傳入int類型
 class PrintClass{
      List list=new List<int>();
      void add(int value){
          this.list.add(value);
      }
      void printInfo(){          
          for(var i=0;i<this.list.length;i++){
            print(this.list[i]);
          }
      }
 }
 */
 class PrintClass<T>{
      List list=new List<T>();
      void add(T value){
          this.list.add(value);
      }
      void printInfo(){          
          for(var i=0;i<this.list.length;i++){
            print(this.list[i]);
          }
      }
 }


void main(){
  List list=new List();
  list.add(12);
  list.add("你好");
  print(list);

  List list2=new List<String>();
  // list2.add(12);  //錯誤的寫法
  list2.add('你好');
  list2.add('你好1');
  print(list2);

  List list3=new List<int>();
  // list3.add("你好");  //錯誤寫法
  list3.add(12); 
  print(list);

  PrintClass p=new PrintClass();
  p.add(1);
  p.add(12);
  p.add(5);
  p.printInfo();

  PrintClass p1=new PrintClass<String>();
  // p1.add(1);//錯誤,只能是String類型
  p1.add("Fay");
  p1.add("sfy");
  p1.printInfo();

}

8.3、泛型接口

/*
Dart中的泛型接口:

    實現數據緩存的功能:有文件緩存、和內存緩存。內存緩存和文件緩存按照接口約束實現。

    1、定義一個泛型接口 約束實現它的子類必須有getByKey(key) 和 setByKey(key,value)

    2、要求setByKey的時候的value的類型和實例化子類的時候指定的類型一致


*/


  // abstract class ObjectCache {
  //   getByKey(String key);
  //   void setByKey(String key, Object value);
  // }

  // abstract class StringCache {
  //   getByKey(String key);
  //   void setByKey(String key, String value);
  // }


  // abstract class Cache<T> {
  //   getByKey(String key);
  //   void setByKey(String key, T value);
  // }


abstract class Cache<T>{
  getByKey(String key);
  void setByKey(String key, T value);
}

class FlieCache<T> implements Cache<T>{
  @override
  getByKey(String key) {    
    return null;
  }

  @override
  void setByKey(String key, T value) {
   print("我是文件緩存 把key=${key}  value=${value}的數據寫入到了文件中");
  }
}

class MemoryCache<T> implements Cache<T>{
  @override
  getByKey(String key) {   
    return null;
  }

  @override
  void setByKey(String key, T value) {
       print("我是內存緩存 把key=${key}  value=${value} -寫入到了內存中");
  }
}
void main(){


    // MemoryCache m=new MemoryCache<String>();

    //  m.setByKey('index', '首頁數據');


     MemoryCache m=new MemoryCache<Map>();

     m.setByKey('index', {"name":"張三","age":20});
}

九、Dart中的lib介紹

9.1、簡單介紹

/*

前面介紹Dart基礎知識的時候基本上都是在一個文件裏面編寫Dart代碼的,但實際開發中不可能這麼寫,模塊化很重要,所以這就需要使用到庫的概念。

在Dart中,庫的使用時通過import關鍵字引入的。

library指令可以創建一個庫,每個Dart文件都是一個庫,即使沒有使用library指令來指定。


Dart中的庫主要有三種:

    1、我們自定義的庫     
          import 'lib/xxx.dart';
    2、系統內置庫       
          import 'dart:math';    
          import 'dart:io'; 
          import 'dart:convert';
    3、Pub包管理系統中的庫  
        https://pub.dev/packages
        https://pub.flutter-io.cn/packages
        https://pub.dartlang.org/flutter/

        1、需要在自己想項目根目錄新建一個pubspec.yaml
        2、在pubspec.yaml文件 然後配置名稱 、描述、依賴等信息
        3、然後運行 pub get 獲取包下載到本地  
        4、項目中引入庫 import 'package:http/http.dart' as http; 看文檔使用


*/


9.2、自定義庫

lib/Animal.dart

class Animal{
  String _name;   //私有屬性
  int age; 
  //默認構造函數的簡寫
  Animal(this._name,this.age);

  void printInfo(){   
    print("${this._name}----${this.age}");
  }

  String getName(){ 
    return this._name;
  } 
  void _run(){
    print('這是一個私有方法');
  }

  execRun(){
    this._run();  //類裏面方法的相互調用
  }
}

main.dart

import 'lib/Animal.dart';
main(){
  var a=new Animal('小黑狗', 20);
  print(a.getName());
}

通過import 路徑 導入自定義庫

9.3、導入系統內置庫

9.3.1、簡單使用


// import 'dart:io';
import "dart:math";
main(){
 
    print(min(12,23));

    print(max(12,25));
    
}

9.3.2、請求網絡

import 'dart:io';
import 'dart:convert';


void main() async{
  var result = await getDataFromZhihuAPI();
  print(result);
  print("---------------");
}


//api接口: http://news-at.zhihu.com/api/3/stories/latest
getDataFromZhihuAPI() async{
  //1、創建HttpClient對象
  var httpClient = new HttpClient();  
  //2、創建Uri對象
  var uri = new Uri.http('news-at.zhihu.com','/api/3/stories/latest');
  //3、發起請求,等待請求
  var request = await httpClient.getUrl(uri);
  //4、關閉請求,等待響應
  var response = await request.close();
  //5、解碼響應的內容
  return await response.transform(utf8.decoder).join();
}

9.3.3、async 和 await


/*
async和await
  這兩個關鍵字的使用只需要記住兩點:
    只有async方法才能使用await關鍵字調用方法
    如果調用別的async方法必須使用await關鍵字


async是讓方法變成異步。
await是等待異步方法執行完成。


*/

void main() async{
  var result = await testAsync();
  print(result);

}

//異步方法
testAsync() async{
  return 'Hello async';
}

9.4、導入第三方庫(pub管理包中的庫)

/*
pub包管理系統:


1、從下面網址找到要用的庫
        https://pub.dev/packages
        https://pub.flutter-io.cn/packages
        https://pub.dartlang.org/flutter/

2、創建一個pubspec.yaml文件,內容如下

    name: xxx
    description: A new flutter module project.
    dependencies:  
        http: ^0.12.0+2
        date_format: ^1.0.6

3、配置dependencies

4、運行pub get 獲取遠程庫

5、看文檔引入庫使用
*/
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
import 'package:date_format/date_format.dart';

main() async {
  var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1";

    // Await the http get response, then decode the json-formatted responce.
    var response = await http.get(url);
    if (response.statusCode == 200) {
      var jsonResponse = convert.jsonDecode(response.body);
     
      print(jsonResponse);
    } else {
      print("Request failed with status: ${response.statusCode}.");
    }


  
    print(formatDate(DateTime(1989, 2, 21), [yyyy, '*', mm, '*', dd]));

}
name: xxx
description: A new flutter module project.
dependencies:
  http: ^0.12.1
  date_format: ^1.0.8

如果不是使用Visual Studio Code 可以通過終端定位到yaml目錄,通過pub get 命令獲取相關依賴

如果出現下面錯誤:

F:\Study\dart\14>pub get
Resolving dependencies...
It looks like pub.dartlang.org is having some trouble.
Pub will wait for a while before trying to connect again.
Got socket error trying to find package http at https://pub.dartlang.org.

在環境變量中添加兩個值:

FLUTTER_STORAGE_BASE_URL:https://storage.flutter-io.cn

 

PUB_HOSTED_URL:https://pub.flutter-io.cn

9.5、Dart中的衝突解決

lib/Person1.dart

class Person{
  String name;
  int age; 
  //默認構造函數的簡寫
  Person(this.name,this.age);  

  Person.setInfo(String name,int age){
    this.name=name;
    this.age=age;
  }

  void printInfo(){   
    print("Person1:${this.name}----${this.age}");
  }
}

lib/Person2.dart

class Person{
  String name;
  int age; 
  //默認構造函數的簡寫
  Person(this.name,this.age);  

  Person.setInfo(String name,int age){
    this.name=name;
    this.age=age;
  }

  void printInfo(){   
    print("Person2:${this.name}----${this.age}");
  }
}

main.dart

/*
1、衝突解決
當引入兩個庫中有相同名稱標識符的時候,如果是java通常我們通過寫上完整的包名路徑來指定使用的具體標識符,甚至不用import都可以,但是Dart裏面是必須import的。當衝突的時候,可以使用as關鍵字來指定庫的前綴。如下例子所示:

    import 'package:lib1/lib1.dart';
    import 'package:lib2/lib2.dart' as lib2;


    Element element1 = new Element();           // Uses Element from lib1.
    lib2.Element element2 = new lib2.Element(); // Uses Element from lib2.

*/

import 'lib/Person1.dart';
import 'lib/Person2.dart' as lib;

main(List<String> args) {
  Person p1=new Person('張三', 20);
  p1.printInfo();


  lib.Person p2=new lib.Person('李四', 20);

  p2.printInfo();

}

9.6、部分導入

lib/myMath.dart

void getName(){
  print('張三');
}
void getAge(){
  print(20);
}
void getSex(){
  print('男');
}

main.dart 

/*
部分導入
  如果只需要導入庫的一部分,有兩種模式:

     模式一:只導入需要的部分,使用show關鍵字,如下例子所示:

      import 'package:lib1/lib1.dart' show foo;

     模式二:隱藏不需要的部分,使用hide關鍵字,如下例子所示:

      import 'package:lib2/lib2.dart' hide foo;      

*/

// import 'lib/myMath.dart' show getAge;

 import 'lib/myMath.dart' hide getName;

void main(){
//  getName();
  getAge();
}

9.7、延遲加載

/*
延遲加載

    也稱爲懶加載,可以在需要的時候再進行加載。
    懶加載的最大好處是可以減少APP的啓動時間。

    懶加載使用deferred as關鍵字來指定,如下例子所示:

    import 'package:deferred/hello.dart' deferred as hello;

    當需要使用的時候,需要使用loadLibrary()方法來加載:

    greet() async {
      await hello.loadLibrary();
      hello.printGreeting();
    }


*/

 

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