Code前端首页关于Code前端联系我们

Flutter开发方法:异步总结最详细

terry 2年前 (2023-09-23) 阅读数 70 #移动小程序

1。 Dart 中基于活动的模型

Flutter开发实战:最详细的异步总结

两个任务队列:

  • 微任务队列微任务队列
  • 活动队列事件队列

“微任务”优先执行,“活动队列”只执行,“队列事件”被执行每次一次,少“微任务”、IO、计时器、点击、事件图像

2。调度

2.1 微任务序列

void main() {
  print("main start");
  scheduleMicrotask(() => print('microtask'));
  print("main end");
}

flutter: main start
flutter: main end
flutter: microtask
复制代码

2.2 事件序列

void main() {
  print("main start");
  Future(() => print('microtask'));
  print("main end");
}

flutter: main start
flutter: main end
flutter: microtask
复制代码

3 Future 和 FutureBuilder

3.1 Future 用法

Future() Future.microtask) Future(.value.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
复制代码

3.2 Future.wait

多任务完成时等待回调

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
  
复制代码

3.3 与Completer的主要区别

手动控制未来时间

  /// 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
复制代码

3.4 FutureBuilder

使用故事:依赖基于异步数据更新 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 使用

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();
            }
          }
        )
      ),
    );
  }

复制代码
Flutter开发实战:最详细的异步总结Flutter开发实战:最详细的异步总结

4 async/await

asnc 声明的方法具有以下含义

  • 该方法返回 future
  • only.出现在async中,该方法会以同步模式执行代码,直到到达第一个wait,它会一直等待直到wait完成才执行下面的代码,但是该方法会返回到第一个wait,
  • 当wait 所指的未来任务完成后,立即执行下一行等待
  • 那里。 async 函数中可能有很多等待。每遇到一个人,他就回到未来。结果和绑定的回调是一样的
  • async函数可能不会发现等待,执行后返回Future
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
复制代码
Flutter开发实战:最详细的异步总结

如图,等待将代码分成两部分。绿色框中的代码将被组合,直到满足等待,并立即返回。可以看到红框内的代码,因为是回调方法,类似于下面的方法

fool() async {
  print('foo E');
  return Future.sync(bar).then((v) => print('foo X $v'));
}
复制代码

5 Stream和StreamBuilder

Stream也是用来接收异步数据的。与 Future 不同的是,它可以接收多个异步响应。可以通过多次运行成功或失败来发送数据或错误异常。使用案例:多次读取数据的异步情况、通过网络下载内容、读取文件等。

5.1 使用 Steam

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
复制代码

5.2 使用 StreamBuilder

StreamBuilder 是一个 UI 组件,用于与流中的 StreamBuilder 事件(数据)交互。 Construilder

StreamBuilder({
  Key key,
  this.initialData,
  Stream<T> stream,
  @required this.builder,
})
复制代码

streambuilder 用法

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
      },
    );
  }
}

复制代码
Flutter开发实战:最详细的异步总结Flutter开发实战:最详细的异步总结

作者:Doctrogg
链接:https://juejin.im/post/5e2028a9f2028a9b0ad2c5
来源:Nuggets
版权归作者所有。如需商业印刷,请联系作者以获得许可。非商业转载请注明来源。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门