- 在Dart中處理耗時(shí)操作(網(wǎng)絡(luò)請求,文件讀取),采用的的處理方式為
單線程 + 事件循環(huán),而在OC,Java中采用的是多線程;
阻塞式調(diào)用與非阻塞式調(diào)用
- 其是操作系統(tǒng)中的概念;
- 其關(guān)注的是程序在等待調(diào)用結(jié)果時(shí)的狀態(tài);
-
阻塞式調(diào)用:在調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起,調(diào)用線程只有在得到調(diào)用結(jié)果之前才能繼續(xù)執(zhí)行; -
非阻塞式調(diào)用:調(diào)用執(zhí)行之后,當(dāng)前線程不會(huì)停止執(zhí)行,只需要過一段時(shí)間來檢查一下有沒有結(jié)果返回即可;
Dart事件循環(huán)
- 事件循環(huán):其將需要處理的一系列事件(包括點(diǎn)擊事件,IO事件,網(wǎng)絡(luò)事件)放在一個(gè)
事件隊(duì)列中,然后不斷的從事件隊(duì)列中取出事件,并執(zhí)行其對應(yīng)需要執(zhí)行的代碼塊,直到事件隊(duì)列清空位置;
Dart的異步操作
- Dart的異步操作有三種,分別為:Future,async和await;
Future
- Future就是一個(gè)受你委托的委托人,你將未來要執(zhí)行的任務(wù)交給他,你告知他任務(wù)類型是
耗時(shí)任務(wù),還是非耗時(shí)任務(wù),然后分類放到事件循環(huán)中去,當(dāng)任務(wù)完成后,它會(huì)第一時(shí)間執(zhí)行回調(diào)方法告知你任務(wù)完成,或者會(huì)等到你委托給他的所有任務(wù)都完成了立馬告知你; - Future可以看成是包裝task任務(wù)的;
- Future的創(chuàng)建方式有如下幾種方式:
-
new Future(task函數(shù))異步 task任務(wù)會(huì)延遲執(zhí)行; -
new Future.sync(task函數(shù))同步 task任務(wù)會(huì)立即執(zhí)行; -
new Future.delayed(延遲時(shí)間,task任務(wù))延遲執(zhí)行task任務(wù);
-
- 案例代碼如下:
void main(List<String> args) {
print("main 函數(shù)開始執(zhí)行");
//根據(jù)任務(wù)創(chuàng)建Future
Future future1 = new Future(Task);
Future future = new Future.sync(() {
print("同步任務(wù)執(zhí)行");
});
Future future2 = new Future(() {
print("task2 執(zhí)行");
});
print("main函數(shù)結(jié)束執(zhí)行");
}
void Task() {
print("task1 執(zhí)行");
}
- 控制臺(tái)執(zhí)行結(jié)果如下:

image.png
void main(List<String> args) {
print("main函數(shù)開始執(zhí)行");
Future future = new Future.delayed(Duration(seconds: 2), () {
print("任務(wù)延遲2秒后 開始執(zhí)行");
});
print("main函數(shù)結(jié)束執(zhí)行");
}
- 控制臺(tái)打印結(jié)果:

image.png
- Future注冊回調(diào),當(dāng)耗時(shí)任務(wù)執(zhí)行完成后,會(huì)執(zhí)行回調(diào)函數(shù),注冊回調(diào)有如下幾種方式:
-
then回調(diào):當(dāng)Future中的任務(wù)完成后,我們往往需要一個(gè)回調(diào),這個(gè)回調(diào)立即執(zhí)行,不會(huì)被添加到事件隊(duì)列,then回調(diào)可支持多個(gè)回調(diào); -
catchError回調(diào):可用來處理異常; -
靜態(tài)方法wait:等待多個(gè)任務(wù)全部完成后回調(diào);
-
- then回調(diào),案例代碼如下:
void main(List<String> args) {
print("main函數(shù)開始執(zhí)行");
Future future = new Future(() {
print("task 執(zhí)行");
});
future.then((value) {
print("task 執(zhí)行完成的回調(diào)");
});
print("main函數(shù)結(jié)束執(zhí)行");
}
- 控制臺(tái)打印結(jié)果:

image.png
- then支持多個(gè)回調(diào),案例代碼如下:
void main(List<String> args) {
print("main函數(shù)開始執(zhí)行");
Future future = new Future(() {
print("task 執(zhí)行");
});
future.then((value) {
print("task 執(zhí)行完成的回調(diào)");
}).then((value) {
print("task 回調(diào)完成之后");
});
print("main函數(shù)結(jié)束執(zhí)行");
}
- 控制臺(tái)打印結(jié)果如下:

image.png
- catchError回調(diào),案例代碼如下:
void main(List<String> args) {
print("main函數(shù)開始執(zhí)行");
new Future(() {
print("task 任務(wù)");
}).then((value) {
print("task 任務(wù)執(zhí)行完成的回調(diào)");
}).then((value) {
print("task 回調(diào)完成之后的處理");
}).catchError((e) {
print("task 任務(wù)執(zhí)行出現(xiàn)異常的回調(diào)");
});
print("main函數(shù)結(jié)束執(zhí)行");
}
- 靜態(tài)方法wait,
多個(gè)異步耗時(shí)操作同時(shí)執(zhí)行,結(jié)果統(tǒng)一處理,案例代碼如下:
void main(List<String> args) {
print("main函數(shù)開始執(zhí)行");
Future future1 = new Future(() {
print("task1");
return 1;
});
Future future2 = new Future(() {
print("task2");
return 2;
});
Future future3 = new Future(() {
print("task3");
return 3;
});
Future future = Future.wait([future1, future2, future3]);
future.then((value) {
print(value);
});
print("main函數(shù)結(jié)束執(zhí)行");
}
- 控制臺(tái)打印結(jié)果如下:

image.png
-
wait函數(shù)返回一個(gè)新的Future,當(dāng)添加的所有Future完成時(shí),會(huì)在新的Future注冊的回調(diào)將被執(zhí)行;
await 與 async
-
在Dart1.9中加入了async和await關(guān)鍵字,有了這兩個(gè)關(guān)鍵字,我們可以更簡潔的編寫異步代碼,而不需要調(diào)用Future相關(guān)的API; - 將 async 關(guān)鍵字作為方法聲明的后綴時(shí),具有如下意義:
- 被修飾的方法會(huì)將一個(gè) Future 對象作為返回值;
- 該方法會(huì)
同步執(zhí)行其中的方法的代碼 直到第一個(gè) await 關(guān)鍵字,然后它暫停該方法其他部分的執(zhí)行; - 一旦由 await 關(guān)鍵字引用的
Future 任務(wù)執(zhí)行完成,await的下一行代碼將立即執(zhí)行;
-
實(shí)現(xiàn)請求的依賴,順序執(zhí)行,案例代碼如下:
import 'dart:io';
main(List<String> args) {
print("main start");
getData();
print("main end");
}
void getData() async {
//鏈?zhǔn)秸{(diào)用
var res1 = await getNetworkData("SF");
print(res1);
var res2 = await getNetworkData(res1);
print(res2);
var res3 = await getNetworkData(res2);
print(res3);
}
//異步函數(shù)
//1.await必須在async函數(shù)中才能使用
//2.async函數(shù)返回的結(jié)果必須是一個(gè)Future
Future getNetworkData(String str) {
return Future(() {
sleep(Duration(seconds: 3));
return "Hello World!!" + str;
});
}
- 控制臺(tái)打印結(jié)果如下:

image.png
-
await必須在async函數(shù)中才能使用; - async函數(shù)
返回的結(jié)果必須是一個(gè)Future; - 實(shí)現(xiàn)多個(gè)請求異步執(zhí)行,回調(diào)結(jié)果統(tǒng)一處理,案例代碼如下:
多核CPU的利用
Isolate
- Dart是單線程的,這個(gè)線程有自己可以訪問的內(nèi)存空間以及需要運(yùn)行的事件循環(huán);
- 我們可以將這個(gè)空間系統(tǒng)稱之為是一個(gè)
Isolate; - 例如Flutter中就有一個(gè)Root Isolate,負(fù)責(zé)運(yùn)行Flutter代碼,比如UI渲染,用戶交互等等;
- 在Isolate中,資源隔離做的非常好,每個(gè)Isolate都有自己的事件循環(huán)與事件隊(duì)列,Isolate之間之間不共享任何資源,只能依靠消息機(jī)制進(jìn)行通信,因此也就沒有資源搶占問題,但是如果只有一個(gè)Isolate,那么意味著我們只能永遠(yuǎn)利用一個(gè)線程,這對于多核CPU來說,是一種資源的浪費(fèi);
Isolate的創(chuàng)建
- 案例代碼:
import 'dart:isolate';
main(List<String> args) {
print("main start");
//不會(huì)阻塞當(dāng)前線程
Isolate.spawn(calc, 100);
print("main end");
}
void calc(int count) {
var total = 0;
for (var i = 0; i < count; i++) {
total += I;
}
print(total);
}
Isolate的通信機(jī)制
- 創(chuàng)建新的Isolate用于處理耗時(shí)操作,然后將耗時(shí)操作的結(jié)果告知Main Isolate(也就是默認(rèn)開啟的Isolate);
- Isolate通過發(fā)送管道(SendPort)實(shí)現(xiàn)消息通信機(jī)制;
- 我們可以在啟動(dòng)并發(fā)Isolate時(shí)將Main Isolate的發(fā)送管道作為參數(shù)傳遞給它;
- 并在執(zhí)行完畢時(shí),可以利用這個(gè)管道給Main Isolate發(fā)送消息;
- 案例代碼:
import 'dart:isolate';
main(List<String> args) async {
print("main start");
//1.創(chuàng)建管道
ReceivePort port = ReceivePort();
//2.創(chuàng)建Isolate
Isolate isolate = await Isolate.spawn<SendPort>(foo, port.sendPort);
//3.監(jiān)聽管道
port.listen((message) {
print(message);
//關(guān)閉管道
port.close();
//Isolate銷毀
isolate.kill();
});
print("main end");
}
void foo(SendPort port) {
return port.send("Hello World");
}
第三方網(wǎng)絡(luò)請求庫
- Dio的引入,如下所示:

image.png
- 在網(wǎng)絡(luò)請求庫Dio的基礎(chǔ)上進(jìn)行封裝,創(chuàng)建了
http_config.dart與http_request.dart兩個(gè)文件,如下所示:
class HttpConfig {
static const String baseUtl = "http://httpbin/org";
static const int timeout = 5000;
}
import 'package:Fluter01/service/http_config.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
class HttpReuquest {
//基礎(chǔ)配置
static final BaseOptions baseOptions = BaseOptions(baseUrl: HttpConfig.baseUtl,connectTimeout: HttpConfig.timeout);
//網(wǎng)絡(luò)請求
static final Dio dio = Dio(baseOptions);
static Future<T> request<T>(String url,{String method = "get",Map<String,dynamic> params,Interceptor interceptor}) async{
//配置
final options = Options(method: method);
//全局?jǐn)r截器
Interceptor dInterceptor = InterceptorsWrapper(
onRequest: (options){
print("請求攔截");
return options;
},
onResponse: (response) {
print("響應(yīng)攔截");
return response;
},
onError: (error){
print("錯(cuò)誤攔截");
return error;
}
);
List<Interceptor> inters = [dInterceptor];
//單獨(dú)設(shè)置的攔截器
if (interceptor != null){
inters.add(interceptor);
}
dio.interceptors.addAll(inters);
//發(fā)送網(wǎng)絡(luò)請求
try {
Response response = await dio.request(url,queryParameters: params,options: options);
return response.data;
} on DioError catch(e) {
return Future.error(e);
}
}
}
- 使用封裝的網(wǎng)絡(luò)請求類:
import 'package:flutter/material.dart';
import 'package:Fluter01/service/http_request.dart';
void main() => runApp(SFMyApp());
class SFMyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: SFHomePage());
}
}
class SFHomePage extends StatefulWidget {
@override
_SFHomePageState createState() => _SFHomePageState();
}
class _SFHomePageState extends State<SFHomePage> {
bool isShowFloatButton = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("基礎(chǔ)widget")),
body: SFHomeContent(),
floatingActionButton: isShowFloatButton
? FloatingActionButton(
child: Icon(Icons.arrow_upward),
onPressed: () {
},
)
: null,
);
}
}
class SFHomeContent extends StatefulWidget {
@override
_SFHomeContentState createState() => _SFHomeContentState();
}
class _SFHomeContentState extends State<SFHomeContent> {
@override
void initState() {
super.initState();
//發(fā)送網(wǎng)絡(luò)請求
// ///1.創(chuàng)建dio對象
// final dio = Dio();
// ///2.發(fā)送網(wǎng)絡(luò)請求
// dio.get("http://httpbin.org/get").then((value) {
// print(value);
// });
HttpReuquest.request("http://httpbin.org/get",params: {"name" : "liyanyan"}).then((value) {
print(value);
});
}
@override
Widget build(BuildContext context) {
return NotificationListener(
onNotification: (ScrollNotification notification){
if(notification is ScrollStartNotification){
print("開始滾動(dòng)");
}else if (notification is ScrollUpdateNotification){
print("正在滾動(dòng) -- 總區(qū)域:${notification.metrics.maxScrollExtent} 當(dāng)前位置: ${notification.metrics.pixels}");
}else if (notification is ScrollEndNotification){
print("結(jié)束滾動(dòng)");
}
return true;
},
child: ListView.builder(
itemBuilder: (BuildContext ctx, int index) {
return ListTile(
leading: Icon(Icons.people),
title: Text("聯(lián)系人$index"),
);
},
itemCount: 100,
),
);
}
}