一、var 變數、final,const常量
- 變數var
變數用關鍵詞var來定義,Dart語言是型別推斷的所以在定義變數的時候可以不用指明變數的型別,例子如下
void main() {
var name = "小明";
var age = 10;
var job;
print(name);
print(age);
print(job);
}
複製程式碼
在上面例子中,定義了變數 name 和 age ,job,其中給name賦值 "小明",根據型別推斷name就是String 型別的,給 age賦值 10,根據型別推斷age 就是 int 型別的。對job沒有賦值job變數的預設值就是null。
需要注意的是變數的型別一旦確定就不能再給他賦不同型別的值。
- 常量final,const
常量用 final 或 const 關鍵字,例子如下
void main() {
final a = "好";
const b = 1;
}
複製程式碼
需要注意的是,常量在定義的時候一定要進行賦值,且定義好以後不能被修改否則會報錯。
二、Dart中的資料型別
在Dart中all is Object ,Dart 中有 numbers(數值型別),strings (字串型別),booleans(布林型別),lists(列表型別),maps(字典型別)等
- 數值型別
在Dart中數值型別只有int 和 double兩種,例子如下
void main() {
int a = 1;
double b = 2;
print(a);
print(b);
}
複製程式碼
上面的例子中定義了整數型別的a,和double 型別的 b,列印結果是
flutter: 1
flutter: 2.0
2.String字串型別
Dart中字串用單引號 '' 或雙引號 "" 來建立,例子如下:
void main() {
var a = "熱愛程式設計";
var b = '哈哈哈哈';
print(a);
print(b);
}
//輸出結果:
//flutter: 熱愛程式設計
//flutter: 哈哈哈哈
複製程式碼
字串的格式化
在Dart 中用 ${} 來進行字串的格式化,例子如下:
void main() {
var a = "熱愛程式設計";
var b = '哈哈哈哈';
var c = "我們都 ${a + b} ";
print(c);
}
//輸出結果為
//flutter: 我們都 熱愛程式設計哈哈哈哈
複製程式碼
上面的例子中字串 a 和 b 可以用 + 號 直接拼接在一起
在字串中可以用反斜槓\來進行字元轉譯
字串的相關方法使用例子如下:
void main() {
var a = "熱愛程式設計";
//判斷是否為空
print(a.isEmpty);
//字串的長度
print(a.length);
//字串的型別
print(a.runtimeType);
}
//輸出結果為:
//flutter: false
//flutter: 4
//flutter: String
複製程式碼
上面例子是字串的常用方法,isEmpty是判斷字串是否為空,length是求字串的長度,runtimeType是求字串的型別。
字串也是一種集合型別,例子如下:
void main() {
var a = "熱愛程式設計";
print(a[1]);
}
//輸出為:
//flutter: 愛
複製程式碼
- bool布林型別
Dart中的布林型別只有 true和false,例子如下:
void main() {
var a = false;
print(a.runtimeType);
}
//輸出結果:
//flutter: bool
複製程式碼
4.List列表型別(陣列型別)
用List來定義列表,可以在<>內指定列表元素的資料型別,例子如下:
void main() {
List<int> a = [10,100,1000];
List<String> b = ["熱", "愛","編","程"];
}
複製程式碼
上面例子中,尖括號中的型別用來指定元素的資料型別,如果列表指定了元素的資料型別,就只能存放該種資料型別的資料。如果想在列表中存放不同型別的資料,可以將列表中元素的型別用dynamic關鍵字宣告為動態型別的,例子如下:
void main() {
List<dynamic> a = [10,"哈哈哈",99.9];
}
複製程式碼
但是在一般開發中我們不需要指定列表的元素型別,因為Dart是可以型別推斷的,所以直接使用var進行宣告即可,上面的例子一般如下宣告:
void main() {
var a = [10,"哈哈哈",99.9];
}
複製程式碼
列表中的常用方法的使用例子如下:
void main() {
var a = [10,"哈哈哈",99.9];
//新增元素
a.add("ccc");
//刪除一個元素
a.remove(10);
//元素個數
a.length;
//...等等其他方法
}
複製程式碼
- Map字典型別
字典定義使用例子如下:
void main() {
Map<String, dynamic> a = {"name": "Flutter" , "languge": "Datr"};
}
複製程式碼
用Map來定義一個字典,在尖括號內來指定字典的key和value的資料型別,需要主要的是和陣列一樣,一旦型別被確定,那麼就必須要和定義的型別一致否則會報錯。
因為 Dart是可以型別推斷的,所以上面的例子可以直接用var來定義如下:
void main() {
var a = {"name": "Flutter" , "languge": "Datr"};
print(a);
}
//輸出為:
//flutter: {name: Flutter, languge: Datr}
複製程式碼
Map可以通過鍵來獲取,設定,新增值,例子如下:
void main() {
var a = {"name": "Flutter" , "languge": "Datr"};
//新增鍵值對
a["version"] = "1.1.0";
//修改鍵值
a["name"] = "Swift";
print(a);
}
//輸出結果:
//flutter: {name: Swift, languge: Datr, version: 1.1.0}
複製程式碼
三、Dart中的運算子
1.算數運算子加"+",減 "-" ,乘"*" ,除"/",取整 "~/",取模%
"+"是用來做加的運算,除了數字型別外,字串,列表,字典也支援相加運算,例子如下:
void main() {
var a = 10 + 20;
var b = "10" + "10";
print(a);
print(b);
}
//列印結果:
//flutter: 30
//flutter: 1010
複製程式碼
"~/" 是取整的運算子,例子如下:
void main() {
var a = 15;
var b = a ~/ 4;
print(b);
}
//列印結果:
//flutter: 3
複製程式碼
再其他運算子與其他程式語言基本一樣不做介紹
- 比較運算子 == ,!= ,> , < , >= ,<=
與其他語言基本一樣不做介紹
3.型別運算子 as,is, is!
as是做型別的轉換
is是判斷是否屬於某個型別
is!是判斷是否不屬於某個型別
例子如下:
void main() {
var dogA = Dog();
var dogB = dogA;
//
if (dogB is Dog ){
dogB.func_swim();
}
//用as來簡化上面的程式碼結果一樣
(dogB as Dog).func_swim();
}
//列印結果;
//flutter: 游泳
//flutter: 游泳
複製程式碼
上面的例子中 可以用as來簡化程式碼。
- ??
“??” 是Dart的空條件運算子,就是取預設值的意思,例子如下
void main() {
var a;
var b = a ?? 1;
print(b);
}
//輸出結果:
//flutter: 1
複製程式碼
上面的例子中, 變數a沒有賦值所以預設為null,在將a賦值給b的時候因為a是null,所以 通過?? 給把1賦值給了a。
5.級聯運算子 “..”
級聯運算子可以對某個物件進行連續的操作而不用生成中間變數,例子如下: 例子一
class Person{
func_one(){
print("Dart語言");
}
func_two(){
print("Flutter使用Dart");
}
}
void main() {
Person()..func_one()..func_two();
}
//列印結果如下:
//flutter: Dart語言
//flutter: Flutter使用Dart
複製程式碼
- 點運算子以及“?.”的使用
點運算子用來訪問物件的屬性或方法,對不確定是否為null的物件可以用“?.”來進行操作,例子如下:
class Person{
var name;
}
void main() {
var p = Person();
print(p?.name);
}
複製程式碼
四、 函式
1.函式的一般書寫格式:
返回值 函式名稱(引數列表){
函式體
}
複製程式碼
例子如下:
void main() {
int func_add(int a,int b){
return a + b;
}
var c = func_add(1, 2);
print(c);
}
//列印結果:
//flutter: 3
複製程式碼
上面例子中main函式是程式的入口, 裡面定義了func_add函式
Dart中的all is物件, 所以可以將函式賦值給一個變數或者將函式作為引數,例子如下;
void main() {
int func_add(int a,int b){
return a + b;
}
var c = func_add;
var d = c(1,2);
print(d);
}
複製程式碼
Dart語言中在定義函式的時候函式的引數型別和返回值型別都可以省略,Dart語言會根據傳入的引數和返回的值來動態推斷。例子如下:
void main() {
func_add(a,b){
return a + b;
}
var c = func_add(1, 2);
print(c);
}
//列印結果
//flutter: 3
複製程式碼
如果某個函式的函式體只有一句話可以用箭頭函式來定義,例子如下:
void main() {
func_add(a,b) => a + b;
var c = func_add(1, 2);
print(c);
}
//輸出結果:
//flutter: 3
複製程式碼
2.可選引數的函式定義
名稱可選引數函式的一般格式為
返回值型別 函式名稱({可選引數列表}){
函式體
}
複製程式碼
可選引數放在{}號內部,例子如下:
void main() {
func_text({a,b}) {
if(a != null){
print(a);
}
if(b != null){
print(b);
}
};
func_text(a: 2);
}
//列印結果
//flutter: 2
上面的例子中定義了函式func_text其中引數 a和b都是可選的,需要注意的是,在呼叫的時候需要引數名稱加:的形式來進行傳引數
複製程式碼
位置可選引數,只需要將可選引數放入中括號即可,例子如下;
void main() {
func_text(a, [b]) {
if(a != null){
print(a);
}
if(b != null){
print(b);
}
};
func_text(2,3);
}
//輸出結果
//flutter: 2
//flutter: 3
複製程式碼
在上面例子中func_text中有兩個引數a和b,其中b 是可選的。在呼叫的時候可以不傳。
函式可選的可以給個預設值,如果沒有預設值函式中取到的引數值為null,,設定預設值以後如果呼叫的時候沒有傳入這個引數,在函式內就會使用預設值,在定義可選引數的時候應該儘量提供一個預設值。
例子如下:
void main() {
func_text(a, [b = 4]) {
if(a != null){
print(a);
}
if(b != null){
print(b);
}
};
func_text(3);
}
//列印如下:
//flutter: 3
//flutter: 4
複製程式碼
3、匿名函式
Dart中沒有名稱的函式是匿名函式,匿名函式可以直接賦值給變數,通過變數來呼叫。例子如下:
void main() {
var a = (b,c){
return b + c;
};
var d = a(1,2);
print(d);
}
//列印如下:
//flutter: 3
複製程式碼
在上面的例子中,把匿名函式賦值給了變數a,然後通過a來呼叫。
五、閉包
閉包是一種特殊的函式。
閉包是定義在函式內部的函式。
閉包能夠訪問外部方法內的區域性變數並持有。
經典例子如下:
void main() {
var func = a();
func();
func();
func();
}
a(){
int count = 0;
func_count(){
print(count ++);
}
return func_count;
}
//列印結果:
//flutter: 0
//flutter: 1
//flutter: 2
複製程式碼
上面例子中, 函式a中的 func_count函式就是閉包,他定義在a函式內,能夠訪問並持有他外部函式的區域性變數count,暫時理解到這裡後面會詳細說明閉包的使用。
六、類
Dart是基於類和繼承的物件導向的語言。物件是類的例項。在類中定義了物件的屬性和方法。
- 自定義類和類的建構函式
Dart中用 class關鍵字來進行類的定義,例子如下:
class Person {
double weight;
int age;
}
複製程式碼
上面的例子中定義了Person類,類中定義了兩個屬性weight和age;我們可以通過Person來建立物件,通過類來建立物件需要呼叫類的建構函式。類的建構函式一般和類的名字一樣。當定義一個類時Dart會預設生成一個沒有引數的建構函式,可以直接通過類的名稱來呼叫。例子如下:
class Person{
var name;
}
void main() {
var p = Person();
print(p?.name);
}
複製程式碼
上面的例子中,定義的Person類可以直接通過Person()來建立物件。類物件中的方法屬性都可以通過點來訪問呼叫。
一般Dart語言的構造方法的書寫格式如下:
class Person{
var name;
var age;
//一般構造方法的書寫格式
Person(this.name,this.age);
}
複製程式碼
2.類的例項方法:
類定義了屬性和方法,一般屬性用來儲存資料,方法用來定義行為。
例子如下:
class Person{
var name;
var age;
//一般構造方法的書寫格式
Person(this.name,this.age);
func_run(){
print("在跑步");
}
}
複製程式碼
上面的例子中定義了方法func_run()就是Person類中的方法。呼叫的例子如下:
void main() {
var p = Person();
p.func_run();
}
複製程式碼
在類中用this來訪問自身的屬性和方法,例子如下:
class Person{
var name;
var age;
//一般構造方法的書寫格式
Person(this.name,this.age);
func_run(){
print(" ${this.name} 在跑步"); //用this訪問name屬性
}
}
複製程式碼
類中還有兩個比較特殊的方法,Setters 和 Getters方法,Setters用來設定物件的屬性,Getters用來獲取物件的屬性。在定義屬性時Dart會預設生成Setters和Getters方法。
- 抽象類和抽象方法
Dart中 在抽象類中可以定義抽象方法,抽象方法是隻有定義沒有函式實現的方法。抽象方法是面向介面開發的基礎。
抽象類用abstract關鍵字來定義。例子如下:
abstract class PersonInterface{
func_run();
}
複製程式碼
上面例子中定義了一個PersonInterface 的介面,裡面只定義了一個func_run()的抽象方法。Person類可以對這個介面進行實現例子如下,用關鍵詞implements來實現一個介面例子如下:
abstract class PersonInterface{
func_run();
}
class Person implements PersonInterface{
var name;
var age;
//一般構造方法的書寫格式
Person(this.name,this.age);
實現介面函式
func_run(){
print(" ${this.name} 在跑步"); //用this訪問name屬性
}
}
複製程式碼
一個類也可以同時實現多個介面。
抽象類不可以被例項化。
- 類的繼承
子類繼承父類,就可以直接使用父類中的屬性和方法。並且子類可以重寫父類中的屬性和方法。Dart中用extends關鍵字來進行類的繼承。例子如下:
class Person{
var name;
var age;
//一般構造方法的書寫格式
Person(this.name,this.age);
func_run(){
print("在跑步");
}
}
class Man extends Person{
//建構函式呼叫夫類的建構函式
Man(name,age) : super(name,age);
func_eat(){
print("正在吃飯");
}
}
複製程式碼
上面的例子中Man類繼繼承了Person類,需要注意的是建構函式不能被繼承,但可以通過super來呼叫父類的方法。子類也可以過載父類的方法。例子如下:
class Person{
var name;
var age;
//一般構造方法的書寫格式
Person(this.name,this.age);
func_run(){
print("在跑步");
}
}
class Man extends Person{
//建構函式呼叫夫類的建構函式
Man(name,age) : super(name,age);
func_eat(){
print("正在吃飯");
}
@override
func_run(){
print("Man在跑步");
}
}
複製程式碼
上面例子中子類過載父類的func_run()方法,其中@override關鍵字用來標註這個方法是子類過載父類的,@override關鍵字可以省略。
- 列舉
列舉用enum來定義。例子如下:
enum Language{
Dart,
Oc,
Swift
}
class Person{
var name;
Language language;
//一般構造方法的書寫格式
Person(this.name,this.language);
}
void main() {
var p = Person();
p.language = Language.Dart;
print(p.language);
}
//輸出:
//Language.Dart
複製程式碼
7、 類的Mixin特性
Mixin是Dart中非常強大的一個功能。Dart語言是單繼承的只能繼承一個父類。很多時候需要集合多個類的功能來實現一個複雜的自定義類,這時候Mixin特性就不錯。
Mixin的功能就是讓一個類把其他類的功能混合進來。例子如下:
mixin Walker{
func_walk(){
print("跑步");
}
}
mixin Swim{
func_swim(){
print("游泳");
}
}
mixin Flying{
func_flying(){
print("飛");
}
}
class Dog with Swim, Walker {
}
void main() {
var dog = Dog();
print(dog.func_walk());
print(dog.func_swim());
}
複製程式碼
程式執行結果:
//flutter: 跑步
//flutter: 游泳
在上面例子中定義了,mixin的跑Walker和游泳Swim,然後讓Dog類通過with 來遵守。Dog類就有了Walker和Swim裡面的功能。
能被用來混合的類是Mixin類,Mixin類不能實現構造方法否則不能被其他類混合,用with關鍵字來進行混合。Mixin也支援多混合。
- 範型
例子如下:
class Person<T>{
T data;
//一般構造方法的書寫格式
Person(this.data);
}
void main() {
var p =Person("xiaoming");
print(p.data);
//列印結果:
//flutter: xiaoming
}
複製程式碼
七、Dart非同步程式設計 async , await , Future的使用
在Dart語言中可以通過 async , await 關鍵字來編寫非同步執行的程式碼。也可以通過Future相關方法處理非同步任務。
-
async 和await關鍵字的使用
void main() { requestData(); print("繼續執行程式"); } requestData(){ print("收到資料"); } 複製程式碼
呼叫 上面函式的列印結果是:
flutter: 收到資料
flutter: 繼續執行程式
可以看出上面例子中的函式是按順序執行的。如果我們模擬真實的網路請求,那麼requestData會有一定的耗時,即應該後列印“收到資料”,先列印“繼續執行程式”。這時候我們就需要用到非同步處理,對上面的例子修改如下:
void main() {
requestData();
print("繼續執行程式");
}
requestData() async {
var data = await "收到的資料";
print(data);
}
複製程式碼
上面程式執行結果為:
//flutter: 繼續執行程式
//flutter: 收到的資料
現在可以看出是先列印了“繼續執行程式”,後列印了“收到的資料”。實現了非同步的效果。
被非同步執行的函式需要用async關鍵字來修飾,且在函式內需要進行滯後處理的語句要用await關鍵字來修飾如上面例子中的 requestData()函式用 async關鍵字修飾, 函式內部 "收到的資料"前用await修飾。
- 非同步和回撥的使用
非同步和回撥一般都是結合在一起來使用的。如上面的例子中,先從網路請求中獲取資料, 接下來把拿到的資料渲染到UI介面上。就是一個非同步回撥的使用例子。該例子如下:
void main() {
requestData(refreshUI);
print("繼續執行程式");
}
refreshUI(data){
print(data);
print("重新整理UI介面");
}
requestData(callBack) async {
var data = await "服務端返回的Json資料";
callBack(data);
}
複製程式碼
上面程式的執行結果是:
//flutter: 繼續執行程式
//flutter: 服務端返回的Json資料
//flutter: 重新整理UI介面
在Dart中函式可以作為引數,在上面的例子中將refreshUI函式當做引數傳給requestData,在後在requestData中拿到資料data後呼叫。
- Future的使用
任意一個 async函式都會返回一個Future物件。我們可以通過Future 的then方法來設定回撥。上面的例子可以改寫為:
void main() {
var future = requestData();
future.then( (data){
refreshUI(data);
});
print("繼續執行程式");
}
refreshUI(data){
print("重新整理UI介面 ${data}");
}
requestData() async {
var data = await "服務端返回的Json資料";
return data;
}
複製程式碼
程式執行輸出結果:
//flutter: 繼續執行程式
//flutter: 重新整理UI介面 服務端返回的Json資料
八、模組的引用
1.用 import來倒入模組
例子:
在lib 資料夾下建立aa.dart檔案,其中aa.dart可以作為模組,在aa.dart中編寫如下程式碼:
void print_func(){
print("aa檔案的函式");
}
複製程式碼
在程式的main.dart檔案中匯入aa.dart檔案,就可以呼叫aa.dart檔案中的print_func()函式了,例子如下:
import "./lib.aa.dart";
main(){
print_func();
//列印結果:
//aa檔案的函式
}
複製程式碼
import 關鍵字用來匯入模組,也可以選擇只匯入某個模組的某一部分,例子如下:
在上面例子中的aa.dart 檔案中新增一個func_run(),func_eat()函式
void print_func(){
print("aa檔案的函式");
}
void func_run(){
pint("我在跑步");
}
void func_eat(){
print("在吃飯");
}
複製程式碼
在main.dart 中用關鍵字show只匯入aa.dart 中的run_func()部分,如果要匯入多個內容,可以使用逗號分割開即可,main.dart中的程式碼如下:
import "./lib.aa.dart" show run_func ;
main(){
run_func();
//列印結果:
//我在跑步
}
複製程式碼
2.模組的重新命名
如果在不同的Dart檔案中定義了相同名稱的函式,將這些檔案匯入並呼叫這個函式的時候就會出錯,這時候我們可以用 as關鍵字來對模組進行重新命名的方式避免錯誤。例子如下:
在lib資料夾下新建一個bb的檔案,在裡面寫如下程式碼:
bb.dart檔案中寫入:
void print_func(){
print("bb檔案的函式");
}
在main.dart中寫如下使用:
import "./lib.aa.dart";
import "./lib.bb.dart";
main(){
print_func();
//執行就會報錯
}
複製程式碼
對於上面的錯誤可以通過用as關鍵字對模組重新命名來避免。例子如下:
在main.dart檔案中
import "./lib.aa.dart";
import "./lib.bb.dart" as bb;
main(){
print_func(); //aa.dart中的
bb.print_func(); //bb.dart中的
//列印結果:
//aa檔案的函式
//bb檔案的函式
}
複製程式碼
簡單的學習筆記
文章預告,下一篇寫Flutter常用控制元件的使用以及佈局