1. Dart event cycle model
- Microtask queue Microtask queue
- Event queue
The “microtask” is preferentially executed, and the “event queue” is executed only when there is no one. The “event queue” is executed once each time, and the “microtask” is less. IO, timer, click, and drawing belong to the events
2. Task scheduling
2.1 MicroTask queue
void main() {
print("main start");
scheduleMicrotask(() => print('microtask'));
print("main end");
}
flutter: main start
flutter: main end
flutter: microtask
Copy the code
2.2 the Event queue
void main() {
print("main start");
Future(() => print('microtask'));
print("main end");
}
flutter: main start
flutter: main end
flutter: microtask
Copy the code
3 the Future with FutureBuilder
3.1 the Future use
Future() Future.microtask() Future.sync() Future.value() Future.delayed() Future.error() Future.sync()
void main() {
print("main start");
// Delay execution
Future.delayed(Duration(seconds: 1), () = >print('Future running in Event Queue in 1 second'));
// Execute the command immediately
Future.sync(() = >print('Synchronous running Future')).whenComplete(() => print('complete'));
// execute asynchronously, then execute sequentially after executing asynchronous methods,
// The catchError method will be executed if an error occurs
// whenComplete is eventually executed with or without errors
Future(() => print('task'))
.then((_) => print('callback1'))
.then((_) => print('callback2'))
.catchError((error) => print("$error"))
.whenComplete(() => print('complete'));
print("main end");
}
// Result outputCreate a Microtask Queue with a Future flutter: complete flutter: task flutter: callback1 flutter: callback2 flutter: complete flutter:1The Future running in the Event Queue seconds laterCopy the code
3.2 the Future. Wait
Wait for multiple tasks to complete a callback
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");
}
/ / output
flutter: main start
flutter: main end
flutter: Hello + Flutter
Copy the code
3.3 Completer
The biggest difference with Future is manual control of completion timing
/// Completer
var completer = Completer();
// Completer contains a future
var future = completer.future;
// Set the future callback after execution
future.then((value) => print("then $value"));
print('do something else');
// You can control the completion time and then execute the then callback
completer.complete("done");
print("main end");
}
/ / output
flutter: main start
flutter: do something else
flutter: main end
flutter: then done
Copy the code
3.4 FutureBuilder
Usage scenario: Rely on asynchronous data to dynamically update the UI. FutureBuilder dynamically builds itself based on the dependent future
FutureBuilder({
this.future, // Dependent future, usually an asynchronous time-consuming task
this.initialData, // Initial data, the default data set by the user
@required this.builder, // Widget builder, which is called multiple times at different stages of Future execution
})
// Build a builder
Function (BuildContext context, AsyncSnapshot snapshot)
// Snapshot contains the status and result information of the current asynchronous task.
// For example, you can obtain the asynchronous task status through snapshot.connectionState
// snapshot.hasError Checks whether an error occurs in the asynchronous task
Copy the code
FutureBuilder use
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() {
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) {
// The request failed
return Text("Error: ${snapshot.error}");
} else {
// Request completed
return Text("Contents: ${snapshot.data}"); }}else {
/ / display loading
returnCircularProgressIndicator(); }})),); }Copy the code
4 async/await
The methods declared by ASNC have the following meanings
- Method returns a Future
- Await can only occur in async
- The method executes the code in the method synchronously until it encounters the first await, waits for the await to complete before executing the code below, but the method returns at the first await,
- As soon as the Future task referenced by await completes, the next line of code from await executes immediately
- Async can have multiple await functions and return a Future with each await, similar to the then string callback
- Async functions can return a Future without await
void main() {
fool();
}
fool() async {
print('foo E');
String v = await bar();
print('foo X $v');
}
bar() async {
print('bar E');
return 'hello';
}
/ / output
flutter: foo E
flutter: bar E
flutter: foo X hello
Copy the code
fool() async {
print('foo E');
return Future.sync(bar).then((v) => print('foo X $v'));
}
Copy the code
5 the Stream and StreamBuilder
A Stream is also used to receive asynchronous data, and unlike a Future can receive multiple asynchronous returns. Data transfer or error exceptions can be triggered by multiple successes or failures. Application scenarios include asynchronous tasks that read data for multiple times, network content downloading, and file reading
5.1 Steam use
void main() {
print('main start');
Stream.fromFutures([
// Return the result after 1 second
Future.delayed(new Duration(seconds: 1), () {
return "hello 1";
}),
// Throw an exception
Future.delayed(new Duration(seconds: 2), () {
throw AssertionError("Error");
}),
// The result is returned after 3 seconds
Future.delayed(new Duration(seconds: 3), () {
return "hello 3";
})
]).listen((data) => print(data), onError: (e) => print(e),
onDone: () => print("Done"));
print('main end');
}
/ / output
flutter: main start
flutter: main end
flutter: hello 1
flutter: Assertion failed
flutter: hello 3
flutter: Done
Copy the code
5.2 StreamBuilder use
StreamBuilder UI component StreamBuilder constructor used in conjunction with a Stream to display changes in events (data) on a Stream
StreamBuilder({
Key key,
this.initialData,
Stream<T> stream,
@required this.builder,
})
Copy the code
StreamBuilder use
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('no Stream');
case ConnectionState.waiting:
return Text('Waiting for data... ');
case ConnectionState.active:
return Text('active: ${snapshot.data}');
case ConnectionState.done:
return Text('Stream closed ');
}
return null; // unreachable}); }}Copy the code