「微任務」優先執行,沒有才執行「事件隊列」,「事件隊列」每次執行一次,「微任務」較少,IO、計時器、點擊、繪製屬於事件markdown
void main() {
print("main start");
scheduleMicrotask(() => print('microtask'));
print("main end");
}
flutter: main start
flutter: main end
flutter: microtask
複製代碼
void main() {
print("main start");
Future(() => print('microtask'));
print("main end");
}
flutter: main start
flutter: main end
flutter: microtask
複製代碼
Future() Future.microtask() Future.sync() Future.value() Future.delayed() Future.error() Future.sync()網絡
void main() {
print("main start");
// 延時執行
Future.delayed(Duration(seconds: 1), () => print('1秒後在Event queue中運行的Future'));
// 同步執行,回當即執行
Future.sync(() => print('同步運行的Future')).whenComplete(() => print('complete'));
// 異步執行,then在異步方法執行完後按順序執行,
// 出現錯誤會執行catchError方法
// 無論有沒有錯誤最終都會執行whenComplete
Future(() => print('task'))
.then((_) => print('callback1'))
.then((_) => print('callback2'))
.catchError((error) => print("$error"))
.whenComplete(() => print('complete'));
print("main end");
}
// 結果輸出
flutter: main start
flutter: 同步運行的Future
flutter: main end
flutter: 在Microtask queue裏運行future
flutter: complete
flutter: task
flutter: callback1
flutter: callback2
flutter: complete
flutter: 1秒後在Event queue中運行的Future
複製代碼
等待多個任務完成後回調app
void main() {
print("main start");
Future.wait([
Future.delayed(Duration(seconds: 2), () => "Hello"),
Future.delayed(Duration(seconds: 4), () => "Flutter")
]).then((results) {
print("${results[0]} + ${results[1]}");
}).catchError((e) => print(e));
print("main end");
}
// 輸出
flutter: main start
flutter: main end
flutter: Hello + Flutter
複製代碼
和Future最大的區別能夠手動控制完成時機less
/// Completer
var completer = Completer();
// completer中包含一個future
var future = completer.future;
// 設置future執行完成後的回調
future.then((value) => print("then $value"));
print('do something else');
// 能夠控制完成時間,而後執行then回調
completer.complete("done");
print("main end");
}
// 輸出
flutter: main start
flutter: do something else
flutter: main end
flutter: then done
複製代碼
使用場景:依賴異步數據動態更新UI. FutureBuilder根據依賴的future動態構建自身異步
FutureBuilder({
this.future, // 依賴的future,一般爲一個異步耗時任務
this.initialData, // 初始數據,用戶設置的默認數據
@required this.builder, // Widget構建器,會被Future執行的不一樣階段屢次調用
})
// builder的構建方法
Function (BuildContext context, AsyncSnapshot snapshot)
// snapshot包含當前異步任務的狀態信息和結果信息,
// 好比能夠經過snapshot.connectionState獲取異步任務狀態
// snapshot.hasError判斷異步任務是否出現錯誤
複製代碼
FutureBuilder使用async
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,
),
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> {
Future<String> mockNetworkData() async {
return Future.delayed(Duration(seconds: 2), () => throw);
}
@override
void initState() {
// is is! 判斷對象是否爲指定類型, 如num,String
assert(sayHello is Function, 'sayHello is not founction');
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: FutureBuilder<String>(
future: mockNetworkData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.connectionState == ConnectionState.done) {
if(snapshot.hasError) {
// 請求失敗
return Text("Error: ${snapshot.error}");
} else {
// 請求完成
return Text("Contents: ${snapshot.data}");
}
} else {
// 顯示loading
return CircularProgressIndicator();
}
}
)
),
);
}
複製代碼
asnc聲明的方法有以下意義ide
void main() {
fool();
}
fool() async {
print('foo E');
String v = await bar();
print('foo X $v');
}
bar() async {
print('bar E');
return 'hello';
}
// 輸出
flutter: foo E
flutter: bar E
flutter: foo X hello
複製代碼
如圖所示,await將代碼割裂成了兩部分,綠框中的代碼會同步直到遇到await會立刻返回一個Future,紅框中的代碼你能夠看做是在then裏面的回調方法,和下面的方法等效
fool() async {
print('foo E');
return Future.sync(bar).then((v) => print('foo X $v'));
}
複製代碼
Stream也用於接收異步數據,與Future不一樣在於能夠接收多個異步返回結果。能夠經過屢次觸發成功或失敗來傳遞數據或錯誤異常 使用場景:屢次讀取數據的異步任務場景,網絡內容下載,文件讀取等函數
void main() {
print('main start');
Stream.fromFutures([
// 1秒後返回結果
Future.delayed(new Duration(seconds: 1), () {
return "hello 1";
}),
// 拋出一個異常
Future.delayed(new Duration(seconds: 2), () {
throw AssertionError("Error");
}),
// 3秒後返回結果
Future.delayed(new Duration(seconds: 3), () {
return "hello 3";
})
]).listen((data) => print(data), onError: (e) => print(e),
onDone: () => print("Done"));
print('main end');
}
// 輸出
flutter: main start
flutter: main end
flutter: hello 1
flutter: Assertion failed
flutter: hello 3
flutter: Done
複製代碼
StreamBuilder用於配合Stream來展現流上事件(數據)變化的UI組件 StreamBuilder構造函數ui
StreamBuilder({
Key key,
this.initialData,
Stream<T> stream,
@required this.builder,
})
複製代碼
StreamBuilder使用this
class _MyHomePageState extends State<MyHomePage> {
Stream<int> counter() {
return Stream.periodic(Duration(seconds: 100), (i) => i);
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: buildStream(context)
),
);
}
Widget buildStream(BuildContext context) {
return StreamBuilder<int>(
stream: counter(),
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('沒有Stream');
case ConnectionState.waiting:
return Text('等待數據...');
case ConnectionState.active:
return Text('active: ${snapshot.data}');
case ConnectionState.done:
return Text('Stream已關閉');
}
return null; // unreachable
},
);
}
}
複製代碼