Dart语言是单线程,非阻塞式调用
- 阻塞式调用:调用结果返回之前,当前线程被启动,只有得到了调用结果之后才会继续执行下一步操作
- 非阻塞式调用:调用执行后,当前的线程不会停止执行,只需要过一段时间来检查一下有没有返回结果
单线程 + 事件循环
Dart事件循环
单线程模型中主要就是在维护着一个事件循环(Event Loop)
伪代码
List eventQueue = [];
var event;
while(true){
if(eventQueue.length > 0){
event = eventQueue.removeAt(0);
event();
}
}
复制代码
Dart异步操作
Dart中的异步操作主要使用 Future 和 async , await
future
import 'dart:io';
main(List<String> args) {
print("start");
// 发送网络请求
var future = NetWork();
print(future);
// 2.拿到结果(dynamic)
future.then((String value){
print(value);
}).catchError((err){
print(err);
}).whenComplete((){
print("代码执行完成"); // Java当中的finaly js当中的complete
});
print("end");
}
// 这是一个阻塞式调用
// String Network(){
// // 这两行代码会阻塞我们的主线程
// sleep(Duration(seconds: 2));
// return "Hello World";
// }
Future<String> NetWork(){
// 1. 将耗时的操作包裹到Future的回调函数中
return Future<String>(() {
sleep(Duration(seconds: 5));
// 1-1 只要有返回结果,那么就执行Future对应的then的回调(Promise-resolve)
// 1-2 如果没有返回结果(错误信息),需要在Future回调中抛出一个异常(Promise-reject)
return "Hello World";
// throw Exception("错误信息的回调");
});
}
复制代码
future的链式调用
import 'dart:io';
main(List<String> args) {
print("main start");
Future((){
// 第一次发送的网络请求
sleep(Duration(seconds: 2));
return "第一次调用的结果";
}).then((res){
// 第二次发送的网络请求
print(res);
sleep(Duration(seconds: 2));
return "第二次调用的结果";
throw Exception("错误信息");
}).then((res){
print(res);
}).catchError((err){
print(err); // 捕获错误信息
});
print("main end");
}
复制代码
future的常见API
import 'dart:io';
main(List<String> args) {
Future.value("value的回调信息").then((res) {
print(res);
});
Future.error("错误信息").catchError((err){
print(err);
});
// 延迟一会在调用
Future.delayed(Duration(seconds: 2),(){
sleep(Duration(seconds: 1));
return "延迟一会在回调的信息";
}).then((res){
print(res);
sleep(Duration(seconds: 5));
return "延迟一会回调后的第二次回调";
}).then((res){
print(res);
});
}
复制代码
async await
import 'dart:io';
main(List<String> args) {
print("main start");
NetWork().then((res){
print(res);
});
print("main end");
}
/** async await的写法
* 1. await 必须在async函数中才能使用
* 2. async函数返回的结果必须是一个Future
*/
Future NetWork() async {
await sleep(Duration(seconds: 2));
return "Hello World";
}
// Future 的写法
// Future NetWork(){
// return Future((){
// sleep(Duration(seconds: 2));
// return 'Helo World';
// });
// }
复制代码
import 'dart:io';
main(List<String> args) {
print("main start");
getData();
print("main end");
}
// void getData(){
// // 调用第一次网络请求
// NetWork("first").then((res){
// print(res);
// return NetWork(res);
// }).then((res){
// print(res);
// return NetWork(res);
// }).then((res){
// print(res);
// });
// }
void getData() async{
var res1 = await NetWork("first");
print(res1);
var res2 = await NetWork(res1);
print(res2);
var res3 = await NetWork(res2);
print(res3);
}
Future NetWork(String str){
return Future((){
sleep(Duration(seconds: 2));
return " Hello World" + str;
});
}
复制代码
多核CPU的利用
dart是单线程语言,如果只能永远使用一个线程,对于多核CPU来说,是一种资源的浪费
线程有自己的可以访问的内存空间以及需要运行的事件循环可以称为一个Isolate
Flutter就有一个Root Isolate,负责Flutter的代码,界面渲染,用户交互...
Isolate之间不共享任何资源,只能依靠消息机制通信,因此就没有资源抢占问题
创建Isolate
import 'dart:isolate';
main(List<String> args) {
print("main start");
// 我们在这里多创建一个线程进行操作 Isolate.spawn(函数(需要在另一个线程执行的函数), 函数的参数)
Isolate.spawn(calc, 100);
print("main end");
}
// 假设会有一个非常消耗资源的计算 这里在另一个线程里执行的
void calc(count){
var total = 0;
for(var i = 0; i < count ; i++){
total += 1;
}
print(total);
}
复制代码
islate之间的通信
import 'dart:isolate';
main(List<String> args) async{
print("main start");
// 1. 创建管道
ReceivePort receivePort = ReceivePort();
// 2. 创建Isolate
Isolate isolate = await Isolate.spawn<SendPort>(foo, receivePort.sendPort);
// 3. 监听管道
receivePort.listen((message){
print(message);
receivePort.close();
isolate.kill();
});
print("main end");
}
void foo(SendPort send){
return send.send("回调的信息");
}
复制代码
上面是单向通信的代码,双向通信我们可以使用Flutter提供的compute函数,内部封装了Isolate的创建和双向通信
compute
Flutter 多线程
Http网络请求
HttpClient
HttpClient是dart自带的请求方法
void Network()async{
// 1.创建HttpClient对象
final http = HttpClient();
// 2.构造请求的Url
final url = Uri.parse('http://t.yushu.im/v2/movie/in_theaters?apikey=0b2bdeda43b5688921839c8ecb20399b');
// 3.构建请求
final request = await http.getUrl(url);
// 4.发送网络请求
final response = await request.close();
if(response.statusCode == HttpStatus.ok){
print(await response.transform(utf8.decoder).join());
}else{
print(response.statusCode);
}
}
复制代码
http库
http库的使用,这个库是官方提供的,没有默认集成到Dart SDK当中,需要在pubspec中依赖它
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:io';
void httpLibrary() async{
// 创建Client
final client = http.Client();
// 构建Url
final url = Uri.parse('http://t.yushu.im/v2/movie/in_theaters?apikey=0b2bdeda43b5688921839c8ecb20399b');
// 发送网络请求
final response = await client.get(url);
// 获取结果
if(response.statusCode == HttpStatus.ok){
print(response.body);
}else{
print(response.statusCode);
}
}
复制代码
dio
dio是一个第三方库,非常流行,支持拦截器,请求取消,Cookie管理,文件上传,文件下载,超时处理.....
使用dio需要在pubspec中依赖它
自己封装的一层网络请求库
import 'package:HF/data/config.dart';
import 'package:dio/dio.dart';
class HttpRequest{
// 基本配置 connectTimeout 连接超时时间 receiveTimeout 发送超时时间 sendTimeout 收到服务器回应的超时时间
static final BaseOptions baseOptions = BaseOptions(baseUrl:HttpConfig.baseURL ,connectTimeout: HttpConfig.timeout);
static final Dio dio = Dio(baseOptions);
static Future<T> request<T>(String url,{
String method = "get",
Map<String,dynamic> params,
Interceptor inter //拦截器
})async{
// 创建个性化配置 也可以在这里设置公共头部headers:
final option = Options(method: method,);
// 全局拦截器
Interceptor dIter = InterceptorsWrapper(
onRequest: (options){
print("请求拦截");
return options;
},
onResponse: (response){
print("响应拦截");
return response;
},
onError: (err){
print("错误拦截");
return err;
}
);
List<Interceptor> inters = [dIter];
// 请求单独拦截器
if(inter != null){
inters.add(inter);
}
// 添加至拦截器当中
dio.interceptors.addAll(inters);
// 发送网络请求
try{
Response response = await dio.request(url,queryParameters: params,options: option);
return response.data;
} on DioError catch(e){
return Future.error(e);
}
}
}
复制代码
最好能将在写一个配置文件
class HttpConfig{
static const String baseURL = "https://httpbin.org";
static const int timeout = 5000;
}
复制代码
使用我们封装好的库
import 'dart:math';
// 导入dio
import 'package:HF/data/http_request.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Flutter Deom",
theme: ThemeData(
primarySwatch: Colors.blue
),
home: HMContent(),
);
}
}
class HMContent extends StatefulWidget {
@override
_HMContentState createState() => _HMContentState();
}
class _HMContentState extends State<HMContent> {
@override
void initState() {
// TODO: implement initState
super.initState();
// 发送网络请求
// 1.创建Dio对象
final dio = Dio();
// 2.发送网络请求
// dio.get("https://httpbin.org/get").then((value) =>{
// print(value)
// });
//
// dio.post("https://httpbin.org/get").then((value) =>{
// print(value)
// });
HttpRequest.request("https://httpbin.org/get",params: {"token":"123456789"}).then((value) => {
print(value)
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("NetWork Test"),
),
body: Container(
child: Text("Hello World"),
),
);
}
}
复制代码