Flutter之异步编程(上)
一、异步
所谓异步表示可以同时干几件事情,不需要任何事情做完就可以做其他的事情,这样可以提高程序的运行效率。Flutter的异步机制涉及关键字有await、async、iterator、interable、stream和itmer等、比较常用的为async和await。
1.线程
- 单线程
顺序执行,自上而下
- 多线程
相当于开辟另一条执行线,让耗时代码在另一条线上运行
- 事件循环
多线程虽然好用,但是在大量并发时,存在着两个极大的缺陷,一个是开辟线程比较耗费资源,另一份是线程的锁问题,多个线程共享一个内存时需要加锁,复杂情况下的锁竞争资源不仅会降低性能更会出现死锁问题。因此又出现了一个基于事件的异步模型,简单来说就是某个单线程中存在一个事件循环和一个事件队列,事件循环不断的从事件队列中取出事件来执行,遇见耗时的事件时,会跳过耗时事件执行后面的事件。
2.Future
未来要发生的事情,相当于一个语法糖,async返回类型默认是Future,所以通常一起使用。
- Dart事件循环
由单个线程支持,根本不需要同步锁定,Dart线程有一个消息循环和两个消息队列-- event队列和microtask队列。
event队列包含所有外来的事件:I/O,mouse events,drawing events,timers,isolate之间的message等。microtask 队列在Dart中是必要的,因为有时候事件处理想要在稍后完成一些任务但又希望是在执行下一个事件消息之前。event队列包含Dart和来自系统其它位置的事件。但microtask队列只包含来自当前isolate的内部代码。
正如下面的流程图,当main方法退出后,event循环就开始它的工作。首先它会以FIFO的顺序执行micro task,当所有micro task执行完后它会从event 队列中取事件并执行。如此反复,直到两个队列都为空。
- 调度任务
将任务添加到Micro Task队列有两种方法
//方法一
scheuleMicrotask(mytask);
void mytask(){}
//方法二
Future.Microtask(mytask);
添加到event队列中
Future(mytask);
举例:
执行过程
void main(){
print("开始执行");
}
//放入事件队列
Future((){
print("这是event事件");
})
//放入MicroTask队列
Future.Microtask((){
print("这是MicroTask队列");
});
print("执行结束");
结果
开始执行
执行结束
这是MicroTask队列
这是event事件
- 延时任务
Future.delayed
//async_async_wait.dart文件
import 'dart:io';
//模拟耗时操作,调用sleep方法睡眠2秒
doTask() async{
//等待其执行完成,耗时2秒
await sleep(const Duration(seconds:2));
return "执行了耗时操作";
}
//定义一个方法用于包装
test() async {
//添加await关键字,等待异步处理
var r = await doTask();
//必需等待await关键字后面的方法doTask执行完成,才执行下一行代码
print(r);
}
void main(){
print("main start");
test();
print("main end");
}
- Future详解
1.创建Future几种方法
Future()
Future.microtask()
Future.sync()
Future.delayed()
Future.error()
sync同步方法
//async_future_sync.dart文件
import 'dart:async';
void main() {
print("main start");
//立即执行
Future.sync((){
print("sync task");
});
//最后执行
Future((){
print("async task");
});
print("main stop");
}
执行结果
main start
sync task
main stop
async task
注册回调
//async_future_then.dart文件
import 'dart:async';
void main() {
print("main start");
Future fu = Future.value('Future的值为30');
// 使用then注册回调
fu.then((res){
print(res);
});
//链式调用,可以跟多个then,注册多个回调
Future((){
print("async task");
}).then((res){
print("async task complete");
}).then((res){
print("async task after");
});
print("main stop");
}
main start
main stop
Future的值为30
顺序输出//链式调用
catchError
//async_future_catch.dart文件
import 'dart:async';
void main() {
//then catch用法
Future((){
print("async task");
}).then((res){
print("async task complete");
}).catchError((e){
print(e);
});
}
//async_future_static_wait.dart文件
import 'dart:async';
void main() {
print("main start");
//任务一
Future task1 = Future((){
print("task 1");
return 1;
});
//任务二
Future task2 = Future((){
print("task 2");
return 2;
});
//任务三
Future task3 = Future((){
print("task 3");
return 3;
});
//使用wait方法等待三个任务完成后回调
Future future = Future.wait([task1, task2, task3]);
future.then((responses){
print(responses);
});
print("main stop");
}
async 和 await
//async_async_wait.dart文件
import 'dart:io';
//模拟耗时操作,调用sleep方法睡眠2秒
doTask() async{
//等待其执行完成,耗时2秒
await sleep(const Duration(seconds:2));
return "执行了耗时操作";
}
//定义一个方法用于包装
test() async {
//添加await关键字,等待异步处理
var r = await doTask();
//必需等待await关键字后面的方法doTask执行完成,才执行下一行代码
print(r);
}
void main(){
print("main start");
test();
print("main end");
}
实例
//async_get_async_data.dart文件
import 'package:dio/dio.dart';
import 'dart:io';
import 'dart:async';
void main(){
//网络请求参数
var params = {'id':'000001'};
//调用网络请求方法
Future future = getAsyncData('http://192.168.2.168:3000/getAsyncData',params: params);
//使用Future的then方法取得返回数据
future.then((value){
//value即为服务端返回数据
print(value);
});
}
//方法后面添加async表示异步方法 返回值为Future
Future getAsyncData(url,{params}) async {
//添加try...catch捕获网络请求异常
try{
//返回对象
Response response;
//实例化Dio对象
Dio dio = Dio();
//设置Post请求编码格式为application/x-www-form-urlencoded
dio.options.contentType = ContentType.parse('application/x-www-form-urlencoded');
//使用dio发起post请求,使用await关键等待返回结果
if(params == null){
response = await dio.post(url);
}else{
response = await dio.post(url,data: params);
}
//当返回状态为200时,表示请求正常返回
if(response.statusCode == 200){
//返回response对象
return response;
}else{
throw Exception('Server exception...');
}
}catch(e){
return print('error:::${e}');
}
}
RefreshIndicator刷新数据 异步处理实例
//async_list_refresh.dart文件
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('RefreshIndicator示例'),
),
body: DropDownRefresh(),
),
);
}
}
//创建一个有状态的组件
class DropDownRefresh extends StatefulWidget {
@override
_DropDownRefreshState createState() => _DropDownRefreshState();
}
class _DropDownRefreshState extends State<DropDownRefresh> {
//列表要展示的数据
List list = List();
//ListView的控制器
ScrollController scrollController = ScrollController();
//页数
int page = 0;
//是否正在加载
bool isLoading = false;
@override
void initState() {
super.initState();
//初始化列表数据
initData();
//添加滚动监听事件
scrollController.addListener(() {
if (scrollController.position.pixels == scrollController.position.maxScrollExtent) {
print('滑动到了最底部');
//上拉加载更多数据
getMoreData();
}
});
}
//初始化列表数据,加延时模仿网络请求
Future initData() async {
//使用Future.delayed延迟一秒执行
await Future.delayed(Duration(seconds: 1),(){
//设置状态渲染列表
setState(() {
//初始15条数据
list = List.generate(15, (i) => '初始数据 $i');
});
});
}
//下拉刷新方法,为list重新赋值
Future onRefreshData() async {
await Future.delayed(Duration(seconds: 1), (){
//设置状态渲染列表
setState(() {
//重新生成20条数据
list = List.generate(20, (i) => '刷新后的数据 $i');
});
});
}
//根据index渲染某一行数据
Widget renderListItem(BuildContext context, int index){
//当index显示list.lenth时显示列表项
if (index < list.length) {
return ListTile(
title: Text(list[index]),
);
}
//当索引大于等于list.length时,显示加载更多数据组件
return showGetMoreWidget();
}
//加载更多时显示的组件,给用户提示
Widget showGetMoreWidget() {
//居中显示'加载中...'
return Center(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'加载中...',
style: TextStyle(fontSize: 16.0),
),
//圆形刷新提示组件
CircularProgressIndicator(
strokeWidth: 1.0,
)
],
),
),
);
}
//上拉加载更多
Future getMoreData() async {
if (!isLoading) {
setState(() {
isLoading = true;
});
//延迟一条生成更多数据
await Future.delayed(Duration(seconds: 1),(){
//设置状态渲染列表
setState(() {
//每上拉一次重新生成5条件数据,添加至现有列表里
list.addAll(List.generate(5, (i) => '第$page次上拉来的数据'));
//当前页自增
page++;
isLoading = false;
});
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// 标题
title: Text(
'下拉刷新 上拉加载更多',
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
),
// 标题居中
centerTitle: true,
// 取消默认阴影
elevation: 0,
backgroundColor: Color(0xffEDEDED),
),
//刷新组件
body: RefreshIndicator(
//刷新回调方法
onRefresh: onRefreshData,
//构建列表
child: ListView.builder(
//列表项渲染
itemBuilder: renderListItem,
//列表项个数
itemCount: list.length + 1,
controller: scrollController,
),
),
);
}
@override
void dispose() {
super.dispose();
scrollController.dispose();
}
}
监听的是上拉的数据,本身组件的方法是下拉更新