1. 程式人生 > 其它 >Flutter系列1-Dart基礎筆記

Flutter系列1-Dart基礎筆記

技術標籤:前端基礎前端

1、變數宣告及命名規則

1、簡介

Dart的開始處,是因為我看見了flutter。其實對於一個會 javaScript 和 java 的來說這些都是理所當然的。我學習的時候比較喜歡記筆記所以我記錄一些這些東西。

其實如果會一些語言,Dart根本不需要花時間。

2、宣告

dart 是一個強大的指令碼類語言,可以不預設先定義變數型別,自動會型別推倒

dart 中定義變數可以通過var關鍵字可以通過型別來申明變數

如:

var str = 'this is var';
String str = 'this is var';
int str = 123
void main() {
    var str = '你好dart';
    var numx = 1234;
    print(str);
    print(numx);
    
    String str1 = '你好dart';
    print(str);
    
    int numx1 = 123;
    print(numx1);
}

定義報錯:

var str = '';
str = 1234; //報錯 A value of type 'int' can't be assigned to a variable of type 'String'.
print(str);
 String str = 12312;//報錯 A value of type 'int' can't be assigned to a variable of type 'String'.

3、命名規則

一、Dart命名規則:

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

2、注意:識別符號開頭不能是數字

3、識別符號不能是保留字和關鍵字

4、變數的名字是區分大小寫的如:age和Age是不同的變數。在實際的運用中也建議不要用一個

5、識別符號(變數名稱)一定要見名思意:變數名稱建議用名詞,方法名稱建議用動詞

二、Dart常量:final和const修飾符

const 值不變 一開始就得賦值

final 可以開始不賦值但是隻能賦值一次;而final不僅僅有const的編譯時常量的特性,最重要的它是執行時常量,並且final是惰性初始化,即在執行時第一次使用前才初始化。可以見下面定義時間的例子。

永遠不變的量,例如 PI = 3.1415926,請使用final或const修飾它,而不是使用var或其他變數型別

 final name = "Bob";
 final String strname = "Bobby";

 const bar = 1000000;
 const double a = 1.123 * bar;

 final date1 = new DateTime.now();
 const date2 = new DateTime().now();//報錯,New expression is not a constant expression.

2、Dart的資料型別

Dart中支援以下資料型別:

一、常用資料型別:

numbers(數值):int、double

String(字串):String

Booleans(布林):bool

List(陣列):在Dart中,陣列是列表物件,所以大多數人只是稱它們為列表

Maps(字典):通常來說,Map是一個鍵值對相關的物件。鍵和值可以是任何型別的物件。每個

1、number型別

int 必須時整型

double 既可以是整型也可以是浮點型

2、String型別

String 定義時 “”“ 單引號定義會保持格式

  String str1 = '111';
  String str2 = "222";
  String str3 = ''' 111 
  111''';

  print(str1);
  print(str2);
  print(str3);

執行結果:
在這裡插入圖片描述
String字串的拼接

  String str1 = '你好';
  String str2 = "Dart";

  print("$str1 $str2");
  print(str1 + str2);

3、Boolean型別

  bool flag = true;
  print(flag);

4、List(陣列/集合)

var l1 = ['aaa','bbb','ccc'];
print(l1);
print(l1.length);
print(l1[0]);
//輸出:
//[aaa, bbb, ccc]
//3
//aaa

var l2 = new List();
l2.add("111");
l2.add("222");
l2.add("333");
print(l2);
//輸出:[111, 222, 333]

//定義list指定型別
var l3  = List<String>();
l3.add("111");
l3.add(222);//報錯,Error: The argument type 'int' can't be assigned to the parameter type 'String'.
print(l3);

5、Maps(字典)

//key必須加上 " 號
var person = {
  "name" : "張三",
  "age" : 20,
  "like" : ["111","222"]
};
print(person);
//輸出:{name: 張三, age: 20, like: [111, 222]}
print(person["name"]);
//輸出:張三

var p = new Map();

p["name"] = "張三";
p["age"] = 20;
p["like"] = ["111","222"];

print(p);
//輸出:{name: 張三, age: 20, like: [111, 222]}

二、很少用的資料型別:

​ Runes:Rune是UTF-32編碼的字串。它可以通過文字轉換成符號表情或者代表特定的文字。

  var clapping = '\u{1f44f}';
  print(clapping);
  print(clapping.codeUnits);
  print(clapping.runes.toList());

  Runes input = new Runes('\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');

  print(new String.fromCharCodes(input));

​ Symbols:Symbol物件表示在Dart程式中宣告的運算子或識別符號。

三、判斷資料型別

is 關鍵字判斷資料型別

var str = '1234';

if(str is String){
  print('是String型別');
}else {
  print('其他');
}
//輸出:是String型別

3、Dart算術運算子/條件表示式/型別轉化

1、運算子

1、算術運算子

+  -  *  /  ~/(取整)  %

2、關係運算符

==  !=  >  <  >=  <=

3、邏輯運算子

!  &&  ||  

4、賦值運算子

基礎賦值運算子 =  ??=
複合賦值運算子 +=  -=  *=  /=  %=  ~/=
int b =10;
b??= 23;
print(b);//輸出:10

int b ;
b??= 23;
print(b);//輸出:23

//上述  ??=  表示如果b為空的話,才進行賦值操作

2、條件表示式

1、if else switch case

2、三目運算子

bool flag = true;
String c = flag? 'true':'false';
print(c);//輸出true

3、?? 運算子

var a ;
var b = a ?? 10;
print(b);//輸出10

var a = 7 ;
var b = a ?? 10;
print(b);//輸出7

3、型別轉化

1、number與String型別之間的轉換

number型別轉換成String型別 toString()

String型別轉換成number型別 parse

String str = '123';
var numx = int.parse(str);
print(numx is int);//輸出true

2、其他型別轉換成Booleans型別

4、Dart迴圈語句

1、for基本語法

for(int i = 1 ; i <= 100 ;i++){
  print(i);
}

2、while/do…while

int  i = 1;
while(i <= 10){
  print(i);
  i++;
}

do{
  print("總會執行一次");

}while(i < 2);

3、continue/break

continue:結束本次迴圈,但是還是會繼續執行當前迴圈。

break:跳出當前迴圈體,結束當前迴圈,但是隻能向外跳出一層。

5、Dart集合型別List/Set/Map

1、List

1、常用屬性

length(長度)、reversed(翻轉)、isEmpty(是否為空)、isNotEmpty(是否不為空)

2、常用方法

add(增加)、addAll(拼接陣列)、indexOf(查詢,需傳入具體值)、remove(刪除,需傳入具體值)、removeAt(刪除,傳入索引值)、fillRange(修改)、insert(index,value)指定位置插入、insertAll(index,list)指定位置插入List、toList(其他型別轉化成List)、join(List轉換成字串)、split(字串轉換成List)

2、Set

set是沒有順序且不能重複的集合。

3、Map

1、常用屬性

keys:獲取所有的key值,values:獲取所有的values值,isEmpty:是否為空,isNotEmpty:是否不為空

2、常用方法

remove(key):刪除指定key的資料、addAll({…}):合併對映,給對映內增加屬性、containsValues:檢視對映內的值,返回true/false

4、迴圈語句 forEach map where any every

  List myList = ["111", "222", "333"];
  myList.forEach((value) {
    print(value);
  });
//輸出:
//111
//222
//333
  List myListnumx = [1, 2, 3, 4];

  var newList = myListnumx.map((e) {
    return e * 2;
  });
  print(newList);//(2, 4, 6, 8)

  var newListWhere = myListnumx.where((e) {
    return e > 2;
  });
  print(newListWhere);//(3, 4)

  //只要有一個滿足條件即返回true
  var f = newList.any((element) {
    return element > 2;
  });
  print(f);//true

  //全部滿足返回true
  var d = newList.every((element) {
    return element > 2;
  });
  print(d);//false

6、Dart中的函式

1、函式的定義

void main(List<String> args) {
  var n = getnumx();
  print(n);//123
  printInfo();//自定義方法!
}

void printInfo() {
  print("自定義方法!");
}
int getnumx() {
  return 123;
}
void main(List<String> args) {
  print(sum(1,2));//3
  print(sumd(1,2));//3
}

int sum(int a,int b){
  return a+b;
}

int sumd(a,b){
  return a+b;
}

2、可選引數

void main(List<String> args) {
  print(getStr("xxx"));//xxx
  print(getStr("xxx",12));//xxx   12
}

String getStr(String name,[int age]){
  if(age != null){
    return "$name   $age";
  }else {
    return name;
  }
}

3、預設引數

void main(List<String> args) {
  print(getStr("xxx"));//xxx   男
  print(getStr("xxx","女",20));//xxx   20   女
 
}

String getStr(String name,[String sex = '男',int age]){
  if(age != null){
    return "$name   $age   $sex";
  }else {
    return "$name   $sex";
  }
}

4、命名引數

注意:傳參和函式那邊的{ }裡面的key定義一致。

void main(List<String> args) {
  print(getStr("xxx"));//xxx   男
  print(getStr("xxx",sex:"女",age:20));//xxx   20   女
 
}

String getStr(String name,{String sex = '男',int age}){
  if(age != null){
    return "$name   $age   $sex";
  }else {
    return "$name   $sex";
  }
}

5、箭頭函式

main(List<String> args) {
  List list = ["111","222","333"];

  list.forEach((element) => {
    print(element)  //這裡面不打分號,只能寫一行,注意啊
  });
}

6、匿名函式

main(List<String> args) {
   //fun是匿名函式
   var fun = (){
    print("xxxx");
  };
  fun(); 
}

7、自執行方法

main(List<String> args) {
  ((){
    print("自執行方法!");
  })();
}

8、方法的遞迴

main(List<String> args) {
  var sum =1;
  fn(n) {
    sum+=n;
    if(n==0){
      return;
    }
    fn(n-1);
  }
  fn(100);
  print(sum);
}

9、閉包

全域性變數:全域性變數常駐記憶體、全域性變數汙染全域性

區域性變數:不常駐記憶體會被垃圾回收機制回收、不會汙染全域性

閉包實現:常駐記憶體但是不汙染全域性

閉包通俗點講就是函式巢狀函式,並且返回裡面的函式。

main(List<String> args) {
  fn(){
    var a = 1;
    return (){
      a++;
      print(a);
    };
  }
  var b = fn();
  b();//2
  b();//3
  b();//4
}

7、Dart中的物件

1、面向物件簡介

面向物件程式設計(OOP)的三個基本特徵是:封裝、繼承、多型

封裝:封裝是物件和類概念的主要特徵。封裝,把客觀事物封裝成抽象的類,並且把自己的部分屬性和方法提供給其他物件。

繼承:面向物件程式語言的一個主要的功能就是”繼承“。繼承可以說是一種能力,繼承實際上也是為了提高程式碼的複用性和可擴充套件性。繼承是使用已存在的類的定義作為基礎建立新類的技術,新類的定義可以增加新的資料或新的功能,也可以用父類的功能,但不能選擇性地繼承父類。

多型:允許將子型別的指標賦值給父類型別的指標,同一個函式呼叫會有不同的執行效果。

Dart也不例外,所有東西都是物件,所有的物件都繼承自Object類。

Dart可以說是一門使用類和單繼承的面嚮物件語言,所有的物件都是類的例項,並且所有的類都是Object的子類。一個類通常由屬性和方法組成。

2、類的建立

class Person{
  String name = "cdx";
  int age = 23;

  void getInfo(){
    print("${this.name}  ${this.age}");
    print(this.name + "  "+ this.age.toString());
  }

  void setInfo(age){
    this.age = age;
  }
}

main(List<String> args) {
  var p1 = new Person();
  print(p1.age); //23
  p1.getInfo();//cdx  23    cdx  23
  p1.setInfo(18);
  print(p1.age);//18
}

3、建構函式

class Person{
  String name = "cdx";
  int age = 23;
  //預設建構函式
  Person(){
    print("建構函式");
  }

  void getInfo(){
    print("${this.name}  ${this.age}");
  }
}

main(List<String> args) {
  var p1 = new Person();
}
//輸出:建構函式
class Person{
  String name = "cdx";
  int age = 23;

  Person(String name , int age){
    this.name = name;
    this.age = age;
  }
  //簡寫形式
  // Person(this.name,this.age);

  void getInfo(){
    print("${this.name}  ${this.age}");
  }
}

main(List<String> args) {
  var p1 = new Person("zs",12);
  p1.getInfo();//zs  12

  var p2 = new Person("ls",16);
  p2.getInfo();//ls  16
}

注意:預設的建構函式只能定義一個。

4、命名建構函式

預設建構函式只能定義一個但是命名建構函式可以定義多個。

class Person{
  String name = "cdx";
  int age = 23;
  //預設建構函式
  Person(this.name,this.age);
  Person.now(){
    print("命名建構函式");
  }

  void getInfo(){
    print("${this.name}  ${this.age}");
  }
}

main(List<String> args) {
  var p1 = new Person.now();//命名建構函式
}

5、私有屬性/私有方法

Dart中是沒有和java一樣有public、private、protected這些訪問修飾符的。

方法:將類抽離成一個檔案,使用 “ _ ” 把一個方法或者屬性變成私有的。

6、getter與setter修飾符

class Rect {
  num height;
  num width;
  Rect(this.height,this.width);
  get area{
    return this.height * this.width;
  }
  set areaHeight(value){
    this.height = value;
  }
}
main(List<String> args) {
  Rect r = new Rect(10, 2);
  print("面積為:${r.area}");//注意呼叫直接通過訪問屬性的方式訪問area
  r.areaHeight = 6;
  print("面積為:${r.area}");
}

7、靜態成員

1、使用static關鍵字來實現類級別的變數和函式。

2、靜態方法不能訪問非靜態成員,非靜態方法可以訪問靜態成員。

class Person {
  static String name = 'cdx';
  static void showName() {
    print(name);
  }
}

main(List<String> args) {
  print(Person.name);
  Person.showName();
}
class Person {
  static String name = 'cdx';
  int age = 23;
  static void showName() {
    print(name);
  }
  void printInfo(){ //非靜態方法可以訪問靜態成員以及非靜態成員
    print(name);//訪問靜態屬性
    print(this.age);//訪問非靜態屬性
  }
}
main(List<String> args) {
  Person p = new  Person();
  p.printInfo();
}

8、操作符

?:條件操作符 as:型別轉換 is:型別判斷 …:級聯操作

class Person {
  String name = 'cdx';
  int age = 23;
  void printInfo(){
    print("${this.name}  ${this.age}");
  }
}

main(List<String> args) {
  Person p1 = new  Person();
  p1.printInfo();//cdx  23
  Person p2;
  //p2.printInfo();//報錯:The method 'printInfo' was called on null.
  p2?.printInfo();
}
p as Person  //型別轉換
class Person {
  String name = 'cdx';
  int age = 23;
  void printInfo(){
    print("${this.name}  ${this.age}");
  }
}

main(List<String> args) {
  Person p1 = new  Person();
  p1.printInfo();//cdx  23
  p1..name='xxx'
    ..age =20
    ..printInfo();//xxx  20
}

9、繼承

1、子類使用extends關鍵詞來繼承父類

2、子類會繼承父類裡面可見的屬性和方法但是不會繼承建構函式

3、子類能複寫符類的方法 getter和setter

class Person {
  String name = 'cdx';
  int age = 23;
  Person(this.name,this.age);
  void printInfo(){
    print("${this.name}  ${this.age}");
  }
}

class Cdx extends Person{
  String sex;
  Cdx(String name, int age,String sex) : super(name, age){
    this.sex = sex;
  }

  void printCdx(){
    print("${this.name}  ${this.age}  ${this.sex} ");
  }

}
main(List<String> args) {
  Cdx c = new  Cdx('xxx',20,'男');
  c.printInfo();//xxx  20
  c.printCdx();//xxx  20  男 
}

10、抽象類

Dart中抽象類主要用於定義標準,子類可以繼承抽象類,也可也實現抽象類介面。

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

2、Dart中的抽象方法不能用abstract宣告,Dart中沒有方法體的方法稱為抽象方法。

3、如果子類繼承抽象類必須要實現裡面的抽象方法。

4、如果把抽象類當作介面實現的話,必須要實現抽象類裡面定義的所有屬性和方法。

5、抽象類不能被例項化,但可以繼承它的子類

extends抽象類和implements的區別:

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

2、如果只是把抽象類當作標準的話我們就要用implement實現抽象類。

//定義一個Animal類必須要求它的子類包含eat方法
//解決方法:用到抽象類
abstract class Animal{
  eat();//抽象方法
}
class Dog extends Animal{
  @override
  eat() {
    print("eat");
  }
}

main(List<String> args) {
  Dog dog = new Dog();
  dog.eat();
}

11、多型

允許將子類型別的指標賦值給父類型別的指標,同一個函式呼叫會有不同的執行效果。

子類的例項賦值給父類的引用。

多型就是父類定義一個方法不去實現,讓繼承他的子類去實現,每個子類有不同的表現。

abstract class Animal{
  eat();//抽象方法
}
class Dog extends Animal{
  @override
  eat() {
    print("Dog eat");
  }
}

class Cat extends Animal{
  @override
  eat() {
    print("Cat eat");
  }
}

main(List<String> args) {
  Animal dog = new Dog();
  dog.eat();//Dog eat

  Animal cat = new Cat();
  cat.eat();//Cat eat
}

12、介面

和java一樣Dart也是有介面的他們之間案對區別是

Dart的介面沒有interface關鍵字定義介面,而是普通類或抽象類都可以作為介面被發現

但是Dart還是有不一樣的地方,如果實現的類是普通類,會將普通類和抽象中的屬性的方法全部需要覆蓋寫一遍。而因為抽象類可以定義抽象方法,普通類不可以,所有一般來說如果要實現java介面那樣的方式,一般使用抽象類。當然也建議使用抽象類定義介面。

abstract class Db{
  String url;
  add();
  save();
  delete();
}
class Mysql implements Db{
  @override
  String url;
  Mysql(this.url);
  @override
  add() {
    print("Mysql add");
  }
  @override
  delete() {
    print("Mysql delete");
  }
  @override
  save() {
    print("Mysql save");
  }
}
main(List<String> args) {
  Mysql mysql = new Mysql("xxxxxxx");
}

13、mixins

中文的意思是混入,其實就是在類中混入其他功能。比如說使用它實現類似多繼承的功能。

但是隨著Dart版本的不斷變化,下面講一下Dart中2.x中使用mixins的條件

1、作為mixins的類只能繼承自Object,不能繼承其他類。

2、作為mixins的類不能有建構函式

3、一個類可以mixins多個mixins類

4、mixins絕不是繼承,也不是介面,而是一一種全新的特性。

//A,B不能繼承其他類,而且A,B不能有建構函式
class A{
  void printA(){
    print("A");
  }
}
class B{
  void printB(){
    print("B");
  }
}
class C with A,B {

}
main(List<String> args) {
  var  c = new C();
  c.printA();
  c.printB();
}

8、泛型

泛型就是解決,類、介面、方法的複用性,以及對不特定資料型別的支援(型別校驗)。

T getData<T>(T value){
  return value;
}
main(List<String> args) {
  print(getData(21));
  print(getData<String>('xxxx'));
}
class PrClass<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]);
    }
  }
}
main(List<String> args) {
  PrClass p = new PrClass<String>();
  p.add("111");
  //p.add(1);//type 'int' is not a subtype of type 'String' of 'value'
  p.printInfo();//輸出:111
}

9、Dart中的庫

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

library指令可以建立一個庫,每個Dart檔案都是一個庫,即使沒有使用library指令來指定。

Dart中的庫主要分為三種:

1、我們自定義的庫

import 'lib/xxx.dart'

2、系統內建庫

import 'dart:math';
import 'dart:io';
import 'dart:convert';
//等等

3、第三方包管理系統中的庫(一般pub中)。

有很多不一一舉例了。

1、需要在自己專案根目錄新建一個pubspec.yaml。

2、在pubspec.yaml檔案中配置名稱、描述、依賴資訊。

3、執行pub get 獲取包下載到本地。

4、專案中引入該庫。

4、最後就是看文件使用它。

10、擴充套件一下async和await

async和await

這兩個關鍵詞的使用只需要記住:

1、只有async方法才能使用await關鍵字呼叫方法。

2、如果呼叫別的async方法必須使用await關鍵字。

async是讓方法變成非同步。

await是等待非同步方法執行完成。

main(List<String> args) async{
  var result = await testAsync();
  print(result);
}

//非同步方法
testAsync() async{
  return 'async';
}