事件循环Event Loop机制
Future就像是盒子里的巧克力糖
http.get("www.baidu.com").then((value) => null).catchError(onError);
//http.get("www.baidu.com") Future刚建成没有完成的状态
//then((value) => null) 正常完成后得到一个值的状态
//catchError(onError) 异常完成后得到一个错误信息的状态
Future<String> getFuture() {
return Future(() => "alice");
//return Future.delayed(Duration(seconds: 2), () => "alice");
}
//----------------------------------------
getFuture().then((value) => print(value)); //then是future完成后要做的操作
Future<String> getFuture() {
return Future(() => "alice");
}
//----------------------------------------
getFuture().then((value) => print(value)); //then是future完成后要做的操作
print('hi');
/*
hi
alice
*/
//因为future会被放到Event Queue里,等Main里的操作执行完才会执行EventQueue里的
void main() {
//event queue,等main执行完,再执行microtask,然后再执行event queue里的任务
Future(() => print('event 1'));
Future.delayed(Duration(seconds: 1), () => print('event 2'));
//microtask会员区,main运行完就会优先运行microtask里的任务
scheduleMicrotask(() => print('microtask 1'));
Future.microtask(() => print('microtask 2'));
Future.value(123).then((value) => print("microtask 3")); //_completed.then()
//直接运行
print("main1");
Future.sync(() => print('sync 1'));
Future.value(getName());
print('main 2');
Future.delayed(Duration(seconds: 1), () => print('delayed')).then((value) {
print('then');
scheduleMicrotask(() => print('micro'));
}).then((value) => print('then2')); //_.then
runApp(MyApp());
}
捕获异常
//用法1
Future<String> getFuture() {
return Future.error(Exception("someting went wrong"));
}
//------------------------------------------------------------
getFuture()
.then((value) => print(value))
.catchError((err) => print(err))
.whenComplete(() => print('completed'));
//用法2
Future<int> getFuture() async {
throw "oops";
}
//---------------------------------
void _incrementCounter() async {
try {
int d = await getFuture();
} catch (err) {
print(err);
}
setState(() {
_counter++;
});
}
Chain
Future<int> getFuture() {
return Future.value(100);
}
//----------------------------------
getFuture()
.then((value) {
print(value);
return value * 2;
})
.then((value) => print(value))
.catchError((err) => print(err))
.whenComplete(() => print('completed'));
/*
I/flutter (12124): 100
I/flutter (12124): 200
I/flutter (12124): completed
*/
async and await
Future<int> getFuture() async {
return 100;
}
//--------------------------------
void _incrementCounter() async {
int d = await getFuture();
print(d);
d = d * 2;
print(d);
setState(() {
_counter++;
});
}
/*
I/flutter (12124): 100
I/flutter (12124): 200
*/
深入了解FutureBuilder组件
Center(
child: FutureBuilder(
future: Future.delayed(Duration(seconds: 2), () => throw ('oops')),
//initialData: 72, //初始值
//snapshot是future最近的状态
builder: (context, snapshot) {
//等待
// if(snapshot.connectionState==ConnectionState.waiting){}
//完成
// if(snapshot.connectionState==ConnectionState.done){}
//有错误
if (snapshot.hasError) {
return Icon(Icons.error, size: 80);
}
//有数据
if (snapshot.hasData) {
return Text("${snapshot.data}", style: TextStyle(fontSize: 72));
}
//等待
return CircularProgressIndicator();
},
),
),
Stream与StreamBuilder组件
定义stream
final future = Future.delayed(Duration(seconds: 1), () => 42);
//定义一个stream
final stream = Stream.periodic(Duration(seconds: 1), (_) => 42);
@override
void initState() {
future.then((value) => print("future conmpleted:$value"));
//监听一个stream
stream.listen((event) {
print("stream:$event");
});
super.initState();
}
StreamBuilder监听
//定义一个StreamController
final controller = StreamController();
//运行结束后关闭stream
@override
void dispose() {
//关闭stream的controller
controller.close();
super.dispose();
}
//
Center(
child: DefaultTextStyle(
//DefaultTextStyle子级统一样式
style: Theme.of(context).textTheme.headline4,
child: Column(
children: [
//往stream里添加事件
RaisedButton(
child: Text('10'), onPressed: () => controller.sink.add(10)),
RaisedButton(
child: Text('1'), onPressed: () => controller.sink.add(1)),
RaisedButton(
child: Text('Hi'),
onPressed: () => controller.sink.add('hi')),
//往stream里添加错误
RaisedButton(
child: Text('Error'),
onPressed: () => controller.sink.addError('oops')),
//关闭stream
RaisedButton(
child: Text('DONE'), onPressed: () => controller.sink.close()),
//定义一个StreamBuilder开始监听stream
StreamBuilder(
stream: controller.stream,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
//none 代表stream或builder为空
case ConnectionState.none:
return Text('NONE:没有数据流');
break;
case ConnectionState.waiting:
return Text('WAITTING:等待数据流');
break;
//连接状态时active的话,代表有数据或者有错误
case ConnectionState.active:
if (snapshot.hasError) {
return Text('ACTIVE:错误:${snapshot.error}');
} else {
return Text('ACTIVE:正常:${snapshot.data}');
}
break;
case ConnectionState.done:
return Text('DONE:数据流已经关闭');
break;
}
return Container();
},
),
],
),
),
),
StreamController.broadcast
//开启广播,允许被很多人监听,开启广播后,数据不会帮你缓存
final controller = StreamController.broadcast();
//第一种监听方式
@override
void initState() {
super.initState();
controller.stream.listen((event) {
print("event:$event");
},
//错误
one rror: (err) => print("ERROR:$err"),
//关闭
onDone: () => print('DONE'));
}
//第二种监听方式
//StreamBuilder
async*
//新建一个Stream方法,持续返回一个时间
Stream<DateTime> getTime() async* {
while (true) {
await Future.delayed(Duration(seconds: 1));
yield DateTime.now();
}
}
//-------------------------------------------------------
//第一种监听方式
getTime().listen((event) {
print('event:$event');
}, onDone: () => print('DONE'));
//第二种监听方式
StreamBuilder(
stream: getTime(),
builder: (context, snapshot) {
...
....
实例:
import 'dart:async';
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _inputController = StreamController.broadcast();
final _scoreController = StreamController.broadcast();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: StreamBuilder(
stream: _scoreController.stream.transform(TallyTransformer()),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("Score:${snapshot.data}");
}
return Text('Score:0');
}),
),
body: Stack(
children: [
...List.generate(
5, (index) => Puzzle(_inputController.stream, _scoreController)),
Align(
alignment: Alignment.bottomCenter,
child: KeyPad(_inputController, _scoreController)),
],
),
);
}
}
class KeyPad extends StatelessWidget {
final _inputController;
final _scoreController;
KeyPad(this._inputController, this._scoreController);
@override
Widget build(BuildContext context) {
return GridView.count(
childAspectRatio: 3 / 1, //改变大小
crossAxisCount: 3,
shrinkWrap: true, //真空包装,把组件压缩成组件自己的大小
physics: NeverScrollableScrollPhysics(), //不要滚动
padding: EdgeInsets.all(0.0), //IOS下边有padding
children: List.generate(9, (index) {
return FlatButton(
shape: RoundedRectangleBorder(),
color: Colors.primaries[index][200], //primaries
onPressed: () {
_inputController.add(index + 1);
_scoreController.add(-2);
},
child: Text(
'${index + 1}',
style: TextStyle(fontSize: 24),
));
}),
);
}
}
class TallyTransformer implements StreamTransformer {
int sum = 0;
StreamController _controller = StreamController();
@override
Stream bind(Stream stream) {
stream.listen((event) {
sum += event;
_controller.add(sum);
});
return _controller.stream;
}
@override
StreamTransformer<RS, RT> cast<RS, RT>() => StreamTransformer.castFrom(this);
}
class Puzzle extends StatefulWidget {
final inputStream;
final scoreStream;
Puzzle(this.inputStream, this.scoreStream);
@override
_PuzzleState createState() => _PuzzleState();
}
class _PuzzleState extends State<Puzzle> with SingleTickerProviderStateMixin {
int a, b, c;
Color color;
double x;
AnimationController _controller;
reset([from = 0.0]) {
c = Random().nextInt(9) + 1;
b = Random().nextInt(8);
a = c - b;
x = Random().nextDouble() * 300;
color = Colors.primaries[Random().nextInt(Colors.primaries.length)][200];
_controller.duration =
Duration(milliseconds: Random().nextInt(5000) + 5000);
_controller.forward(from: from);
}
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
reset(Random().nextDouble());
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
reset();
widget.scoreStream.add(-3);
}
});
widget.inputStream.listen((input) {
if (input == a + b) {
reset();
widget.scoreStream.add(5);
}
});
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Positioned(
left: x,
top: 600 * _controller.value - 100,
child: Container(
decoration: BoxDecoration(
color: color.withOpacity(0.5),
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.circular(24)),
padding: EdgeInsets.all(8.0),
child: Text('$a+$b', style: TextStyle(fontSize: 24)),
),
);
},
);
}
}