Mixin
備注:子類沒有重寫超類A方法的前提下,如果2個(gè)或多個(gè)超類擁有相同簽名的A方法瑟俭,那么子類會(huì)以繼承的最后一個(gè)超類中的A方法為準(zhǔn)障斋。
如果子類自己重寫了A方法則以本身的A方法為準(zhǔn)。
泛型-泛型函數(shù)
main() {
? K addCache<K, V>(K key, V value) {
? ? K temp = key;
? ? print('${key}: ${value}');
? ? return temp;
? }
? var key = addCache('dongnao', 'damon');
? print(key);
}
備注:Dart1.21開始可以使用泛型函數(shù)泪掀。
泛型函數(shù)可以在以下幾個(gè)地方使用類型參數(shù):
? ? ? ? <1>? ? 函數(shù)的返回值類型听绳。
? ? ? ? <2>? ? 參數(shù)的類型。
? ? ? ? <3>? ? 局部變量的類型异赫。
泛型-構(gòu)造函數(shù)泛型
main() {
? var p = Phone<String>('123456');
? print(p.mobileNumber);
}
class Phone<T> {
? final T mobileNumber;
? Phone(this.mobileNumber);
}
備注:Dart1.21開始可以使用泛型函數(shù)椅挣。
泛型函數(shù)可以在以下幾個(gè)地方使用類型參數(shù):
? ? ? ? <1>? ? 函數(shù)的返回值類型。
? ? ? ? <2>? ? 參數(shù)的類型塔拳。
? ? ? ? <3>? ? 局部變量的類型贴妻。
泛型-泛型限制
main() {
? var footMassage = FootMassage();
? var m = Massage<FootMassage>(footMassage);
? m.massage.doMassage();
}
class Massage<T extends FootMassage > {
? final T massage;
? Massage(this.massage);
}
class FootMassage {
? void doMassage() {
? ? print('腳底按摩');
? }
}
備注:實(shí)現(xiàn)泛型類型時(shí),您可能希望限制其參數(shù)的類型蝙斜,可以在<>里面使用extends名惩。
泛型-與java區(qū)別
Java中的泛型信息是編譯時(shí)的,泛型信息在運(yùn)行時(shí)是不存在的
Dart的泛型類型是固化的孕荠,在運(yùn)行時(shí)也有可以判斷的具體類型
var names = List<String>();
print(names is List<String>);//true
print(names.runtimeType); // List<String>
備注:在Java中娩鹉,可以測試對(duì)象是否為List,但無法測試它是否是List<String>稚伍。
庫-使用核心庫
使用import關(guān)鍵字來載入庫:
import "dart:math";
void main() {
? print(sqrt(4));//開平方 2.0
}
備注:import 后的必須參數(shù)為庫 的 URI弯予。(Uniform?Resource?Identifier統(tǒng)一資源標(biāo)識(shí)符)
對(duì)于內(nèi)置的庫,URI 使用特殊的 dart: scheme个曙。
對(duì)于其他的庫锈嫩,你可以使用文件系統(tǒng)路徑或者 package: scheme。
庫-載入第三方庫
1.編寫pubspec.yaml:
dependencies:
? flutter:
? ? sdk: flutter
? cupertino_icons: ^0.1.0
? dio: ^2.1.0
2.調(diào)用
import "package:dio/dio.dart";
void main() {
? getHttp();
}
void getHttp() async {
? try {
? ? Response response = await Dio().get("https://www.baidu.com");
? ? print(response);
? } catch (e) {
? ? print(e);
? }
}
庫-指定庫前綴
如果兩個(gè)庫有沖突的標(biāo)識(shí)符垦搬,可以為其中一個(gè)或兩個(gè)庫都指定前綴:
import 'MyLib1.dart' as lib1;
import 'MyLib2.dart' as lib2;
void main() {
? var myLib = lib1.MyLib();
? var myLib2 = lib2.MyLib();
}
庫-選擇性載入
show-只載入庫的某些部分
hide-篩選掉庫的某些部分
import 'Mylib1.dart' as lib1 show Test;
import 'Mylib2.dart' as lib2 hide Test;
var test = lib1.Test();
var lib = lib2.MyLib();
備注:果只使用庫的一部分功能呼寸,則可以選擇需要導(dǎo)入的 內(nèi)容。
庫-延遲載入
使用deferred as導(dǎo)入
使用標(biāo)識(shí)符調(diào)用loadLibrary()加載庫
import 'MyLib1.dart' deferred as lazyLib;
void main() {
? lazyLoad();
}
lazyLoad() async {
? await lazyLib.loadLibrary();
? var t = lazyLib.Test();
? t.test();
}
備注:使用 await 關(guān)鍵字暫停代碼執(zhí)行一直到庫加載完成猴贰。
可提高程序啟動(dòng)速度对雪。
用在不常使用的功能。
用在載入時(shí)間過長的包米绕。
執(zhí)行 A/B 測試瑟捣,例如 嘗試各種算法的 不同實(shí)現(xiàn)。
庫-自定義庫
1.//mylib/mylib.dart
library mylib;
part 'util.dart';
part 'tool.dart';
void printMyLib() => print('mylib');
2.//mylib/tool.dart
part of mylib;
void printTool() => print('tool');
3.import 'mylib/mylib.dart';
void main() {
? printMyLib();
? printUtil();
? printTool();
}
備注:part 可以把一個(gè)庫分開到多個(gè) Dart 文件中栅干。
或者我們想讓某一些庫共享它們的私有對(duì)象的時(shí)候迈套,可以需要使用part。
import不會(huì)完全共享作用域碱鳞,而part之間是完全共享的桑李。如果說在A庫中import了B庫,B庫import了C庫,A庫是沒有辦法直接使用C庫的對(duì)象的芙扎。而B,C若是A的part,那么三者共享所有對(duì)象填大。并且包含所有導(dǎo)入戒洼。
異步-async和await
void main(){
? getName1();
? getName2();
? getName3();
}
Future getName1() async {
? await getStr1();
? await getStr2();
? print('getName1’);
}
getStr1() {
? print('getStr1’);
}
getStr2() {
? print('getStr2’);
}
getName2() {
? print('getName2’);
}
getName3() {
? print('getName3’);
}
備注:await關(guān)鍵字必須在async函數(shù)內(nèi)部使用
await表達(dá)式可以使用多次
異步-then,catchError,whenComplete
void main() {
? new Future(() => futureTask())//異步任務(wù)的函數(shù)
? ? ? .then((m) => "result:$m")//任務(wù)執(zhí)行完后的子任務(wù)
? ? ? .then((m) => m.length) //其中m為上個(gè)任務(wù)執(zhí)行完后的返回的結(jié)果
? ? ? .then((m) => printLength(m))
? .catchError(print)
? ? ? .whenComplete(() => whenTaskCompelete());//所有任務(wù)完成后的回調(diào)函數(shù)
}
備注:
如果需要監(jiān)聽“完畢”這個(gè)狀態(tài),那么用whenComplete,需要監(jiān)聽“成功”這個(gè)狀態(tài)允华,用then圈浇,需要監(jiān)聽“失敗”這個(gè)狀態(tài),用catchError靴寂。
如果重寫了test方法磷蜀,test返回true就可以在catchError的onError方法里捕獲到異常,如果test返回false百炬,就把該異常繼續(xù)拋出而不會(huì)在catchError方法里被捕獲褐隆,如果不寫test默認(rèn)實(shí)現(xiàn)一個(gè)返回true的test方法
異步-Event-Looper
備注:一個(gè)消息循環(huán)的職責(zé)就是不斷從消息隊(duì)列中取出消息并處理他們直到消息隊(duì)列為空。
消息隊(duì)列中的消息可能來自用戶輸入剖踊,文件I/O消息庶弃,定時(shí)器等。例如上圖的消息隊(duì)列就包含了定時(shí)器消息和用戶輸入消息德澈。
Dart中的Main Isolate只有一個(gè)Event Looper歇攻,但是存在兩個(gè)Event Queue: Event Queue以及Microtask Queue。
異步-Event Queue和Microtask Queue
備注:優(yōu)先全部執(zhí)行完Microtask Queue中的Event梆造。
直到Microtask Queue為空時(shí)缴守,才會(huì)執(zhí)行Event Queue中的Event。
當(dāng)Event Looper正在處理Microtask Queue中的Event時(shí)候镇辉,Event Queue中的Event就停止了處理了屡穗,此時(shí)App不能繪制任何圖形,不能處理任何鼠標(biāo)點(diǎn)擊忽肛,不能處理文件IO等等鸡捐。
繪制圖形,處理鼠標(biāo)點(diǎn)擊麻裁,處理文件IO等都是在Event Queue里完成的箍镜。
異步-任務(wù)調(diào)度
使用Future類,可以將任務(wù)加入到Event Queue的隊(duì)尾
使用scheduleMicrotask函數(shù)煎源,將任務(wù)加入到Microtask Queue隊(duì)尾
異步-new Future()
void main(){
? testFuture();
}
void testFuture() {
? Future f = new Future(() => print('f1'));
? Future f1 = new Future(() => null);
? //Future f1 = new Future.delayed(Duration(seconds: 1) ,() => null);
? Future f2 = new Future(() => null);
? Future f3 = new Future(() => null);
? f3.then((_) => print('f2'));
? f2.then((_) {
? ? print('f3');
? ? new Future(() => print('f4'));
? ? f1.then((_) {
? ? ? print('f5');
? ? });
? });
? f1.then((m) {
? ? print('f6');
? });
? print('f7');
}
備注:使用new Future將任務(wù)加入event隊(duì)列色迂。
Future中的then并沒有創(chuàng)建新的Event丟到Event Queue中,而只是一個(gè)普通的Function Call手销,在FutureTask執(zhí)行完后歇僧,立即開始執(zhí)行。
如果在then()調(diào)用之前Future就已經(jīng)執(zhí)行完畢了,那么任務(wù)會(huì)被加入到microtask隊(duì)列中诈悍,并且該任務(wù)會(huì)執(zhí)行then()中注冊的回調(diào)函數(shù)祸轮。
使用Future.value構(gòu)造函數(shù)的時(shí)候,就會(huì)上一條一樣侥钳,創(chuàng)建Task丟到microtask Queue中執(zhí)行then傳入的函數(shù)适袜。
Future.sync構(gòu)造函數(shù)執(zhí)行了它傳入的函數(shù)之后,也會(huì)立即創(chuàng)建Task丟到microtask Queue中執(zhí)行舷夺。
當(dāng)任務(wù)需要延遲執(zhí)行時(shí)苦酱,可以使用new Future.delay()來將任務(wù)延遲執(zhí)行。
異步-scheduleMicrotask()
import 'dart:async';
void main(){
? testFuture();
}
void testScheduleMicrotask(){
? scheduleMicrotask(() => print('s1'));
? new Future.delayed(new Duration(seconds: 1), () => print('s2'));
? new Future(() => print('s3')).then((_) {
? ? print('s4');
? ? scheduleMicrotask(() => print('s5'));
? }).then((_) => print('s6'));
? new Future(() => print('s7'));
? scheduleMicrotask(() => print('s8'));
? print('s9');
}
備注:如果可以给猾,盡量將任務(wù)放入event隊(duì)列中疫萤。
使用Future的then方法或whenComplete方法來指定任務(wù)順序。
為了保持你app的可響應(yīng)性敢伸,盡量不要將大計(jì)算量的任務(wù)放入這兩個(gè)隊(duì)列扯饶。
大計(jì)算量的任務(wù)放入額外的isolate中。
生成器-同步生成器
Main(){
? var it = getSyncGenerator(5).iterator;
? while (it.moveNext()) {
? ? print(it.current);
? }
}
Iterable<int> getSyncGenerator(int n) sync* {
? print('start');
? int k = 0;
? while (k < n) {
? ? yield k++;
? }
? print('end');
}
備注:使用sync*池颈,返回的是Iterable對(duì)象帝际。
yield會(huì)返回moveNext為true,并等待 moveNext 指令。
調(diào)用getSyncGenerator立即返回Iterable對(duì)象饶辙。
調(diào)用moveNext方法時(shí)getSyncGenerator才開始執(zhí)行蹲诀。
生成器-異步生成器
Main(){
//getAsyncGenerator(5).listen((value) => print(value));
? StreamSubscription subscription = getAsyncNumIterator(5).listen(null);
? subscription.onData((value) {
? ? print(value);
? ? if(value>=2){
? ? ? subscription.pause();
? ? }
? });
}
Stream<int> getAsyncGenerator(int n) async* {
? print('start');
? int k = 0;
? while (k < n) {
yield k++;
? }
? print('end');
}
備注:使用async*,返回的是Stream對(duì)象弃揽。
yield不用暫停脯爪,數(shù)據(jù)以流的方式一次性推送,通過StreamSubscription進(jìn)行控制。
調(diào)用getAsyncGenerator立即返回Stream,只有執(zhí)行了listen矿微,函數(shù)才會(huì)開始執(zhí)行痕慢。
listen返回一個(gè)StreamSubscription 對(duì)象進(jìn)行流監(jiān)聽控制。
可以使用StreamSubscription對(duì)象對(duì)數(shù)據(jù)流進(jìn)行控制涌矢。
生成器-遞歸生成器
Main(){
? var it = getSyncRecursiveGenerator(5).iterator;
? while (it.moveNext()) {
? ? print(it.current);
? }
}
Iterable<int> getSyncRecursiveGenerator(int n) sync* {
? if (n > 0) {
? ? yield n;
? ? yield* getSyncNumDownFrom(n - 1);
? }
}
備注:yield* 以指針的方式傳遞遞歸對(duì)象掖举,而不是整個(gè)同步對(duì)象。
隔離-Isolates
所有Dart代碼都在隔離區(qū)內(nèi)運(yùn)行娜庇,而不是線程塔次。每個(gè)隔離區(qū)都有自己的內(nèi)存堆,確保不會(huì)從任何其他隔離區(qū)訪問隔離區(qū)的狀態(tài)名秀。
備注:Dart沒有共享內(nèi)存的并發(fā)励负,沒有競爭的可能性所以不需要鎖,也就不用擔(dān)心死鎖的問題匕得。
isolate之間沒有共享內(nèi)存继榆,所以他們之間的通信唯一方式只能是通過Port進(jìn)行,而且Dart中的消息傳遞總是異步的。
isolate神似Thread略吨,但實(shí)際上兩者有本質(zhì)的區(qū)別集币。操作系統(tǒng)內(nèi)的線程之間是可以有共享內(nèi)存的而isolate沒有,這是最為關(guān)鍵的區(qū)別翠忠。
元數(shù)據(jù)(注解)-@deprecated
main() {
? dynamic tv = new Television();
? tv.activate();
? tv.turnOn();
}
class Television {
? @deprecated
? void activate() {
? ? turnOn();
? }
? void turnOn() {
? ? print('Television turn on!');
? }
}
備注:所有的 Dart 代碼都可以使用: @deprecated 和 @override鞠苟。
元數(shù)據(jù)(注解)-自定義
備注:在java中,如果自定義一個(gè)注解负间,需要添加 @Target 作用域注解,@Retention 注解類型注解姜凄,添加 @interface政溃,然后定義注解參數(shù)。
構(gòu)造方法定義為編譯時(shí)常量