Future是一个不会马上完成的计算过程,说的通俗一点就是一个异步执行过程,需要配合async和await一起使用。不会阻塞在此之后的代码,等待计算完成后才会返回结果。
类似于JavaScript中的Promise
和async
、await
。
void main() {
requestApi();
doSomething1();
doSomething2();
}
doSomething1() {
print("doSomething1");
}
doSomething2() {
print("doSomething2");
}
/// 异步请求数据
Future requestApi() async {
....
return
}
由于requestApi()
是个异步函数,程序运行后,不会等待函数执行完成,下面的代码也会立即开始执行。
如果想在异步函数返回结果后再做其他操作,可以使用then()
方法来监听。
void main() {
requestApi().then((value) {
/// 结果返回,开始处理
showApiData(value);
});
print("程序开始运行...");
}
............
showApiData(dynamic value){
print("展示获取的数据: $value");
}
const FutureBuilder({
Key? key,
this.future,
this.initialData,
required this.builder,
})
FutureBuilder会基于传入的future的返回结果来构建Widget。
class FutureBuilderDemo extends StatefulWidget {
const FutureBuilderDemo({Key key}) : super(key: key);
@override
_FutureBuilderDemoState createState() => _FutureBuilderDemoState();
}
class _FutureBuilderDemoState extends State {
Future futureData;
@override
void initState() {
super.initState();
/// ui初始化时开始网络请求数据
futureData = getData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FutureBuilder 测试'),
),
body: Container(
child: Center(
child: FutureBuilder(
future: futureData,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Text("获取的数据==${snapshot.data}");
} else if (snapshot.hasError) {
return Icon(Icons.error_outline);
} else {
return CircularProgressIndicator();
}
}),
),
),
);
}
Future getData() async {
/// 模拟网络请求,等待5秒返回结果
await Future.delayed(Duration(seconds: 5));
/// 返回一个错误
// return Future.error("error");
/// 返回一个成功的结果
return "Hello,world";
}
}
Stream是一系列异步事件的序列,相当于一个异步的跌代器(Iterable)。不同于Future只是一个事件执行过程,Stream可以发送执行多个事件。使用场景不同。
创建方式有2种,一个是单订阅的Stream,一种是能多订阅的流,也就是可以广播。
订阅后(listen)会返回一个StreamSubscription,就是一个观察者。
2种方式的构造方法都有一个可选参数sync
,默认为false。
..........
bool sync = false}) {
return sync
? _SyncStreamController(....)
: _AsyncStreamController(...);
通过源码可以看出,sync
为false创建的是一个异步事件StreamController, sync
为true时创建的是一个同步StreamController。因为大部分场景下使用Stream都是为了异步,所以我们直接不传入即可。
/// 直接使用构造函数
StreamController _controller = StreamController();
StreamSubscription subscription = _controller.stream.listen((event) {
print("subscription 接收到 $event");
});
void main() {
/// 使用工厂方法构造可广播的Controller
StreamController _controller = StreamController.broadcast();
/// 使用多个观察者订阅同一个Stream.
StreamSubscription subscription1 =
_controller.stream.listen((event) => print("sub1 接收到 $event"));
StreamSubscription subscription2 =
_controller.stream.listen((event) => print("sub2 接收到 $event"));
StreamSubscription subscription3 =
_controller.stream.listen((event) => print("sub3 接收到 $event"));
/// 发送事件后,所有已订阅的观察者的都能接收到事件。
_controller.add("Hello");
}
运行多次,打印结果都如下不变:
sub1 接收到 Hello
sub2 接收到 Hello
sub3 接收到 Hello
Process finished with exit code 0
结论:
事件订阅(
listen
)的越早,接收到事件的优先级越高。
使用完事件后或者在Flutter中Widget关闭时,记得也同时关闭Stream。
_controller.stream.listen((event) {}, onDone: () => print("收到onDone事件"));
_controller.close();
subscription.cancel();
关闭后会自动触发onDone回调方法。
在界面中,一般使用StreamBuilder来来配合Stream使用。可以实现多状态界面。
/// 定义3种ui状态
enum UIState { type_1, type_2, type_3 }
class StreamBuilderDemo extends StatefulWidget {
const StreamBuilderDemo({Key key}) : super(key: key);
@override
_StreamBuilderDemoState createState() => _StreamBuilderDemoState();
}
class _StreamBuilderDemoState extends State {
StreamController _controller;
@override
void initState() {
super.initState();
/// 初始化controller
_controller = StreamController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('StreamBuilder测试'),
),
body: Container(
// height: double.infinity,
child: Center(
child: StreamBuilder(
/// 传入stream
stream: _controller.stream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
/// hasData代表有接收到事件
var data = snapshot.data;
Widget widget;
///根据返回不回的类型,展示不同的图片
switch (data) {
case UIState.type_1:
widget = Icon(Icons.timer, size: 100);
break;
case UIState.type_2:
widget = Icon(Icons.done, size: 100);
break;
case UIState.type_3:
widget = Icon(Icons.ac_unit, size: 100);
break;
}
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
widget,
Text("$data"),
],
);
} else if (snapshot.hasError) {
/// 接收到错误事件
return Icon(Icons.error_outline_rounded, size: 100);
} else {
/// 什么都没有,代表没还有接收到事件
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
Text("初始化中,还没接收到收到状态"),
],
);
}
}),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => generateState(), child: Icon(Icons.add)),
);
}
/// 随机生成不同的状态,发送事件
generateState() {
var randomIndex = Random().nextInt(UIState.values.length);
_controller.add(UIState.values[randomIndex]);
}
@override
void dispose() {
super.dispose();
/// 回收资源
_controller.close();
}
}