Flutter怎么处理耗时操作?(异步和线程)

2021-06-23  本文已影响0人  shiyueZ

Flutter是单线程任务执行模式,默认情况下只会在主线程运行。那么碰到耗时操作如:网络请求、图片加载、数据库操作等,Flutter该如何处理呢?

Dart提供了两个关键词来实现异步操作:asyncawait,这两个关键词要配合使用,如:

loadData() async {
  String dataURL = "https://jsonplaceholder.typicode.com/posts";
  http.Response response = await http.get(dataURL);
  setState(() {
    widgets = json.decode(response.body);
  });
}

上面是一个典型的网络请求方法,使用async来表示loadData函数是一个异步操作,当运行到await代码时,表示有任务需要等待,CPU会去调度执行其他IO操作。过一段时间CPU通过事件循环会轮询一次,看某个协程是否任务已经处理完成,有返回结果可以被继续执行,如果可以被继续执行的话,则会沿着上次离开时指针指向的位置继续执行,也就是await标志的位置,执行后面的setState()刷新UI的操作;与iOS的异步操作有点类似。

使用async会返回一个Future结果,Future也是Dart提供的一个关键词,可以通过链式调用,后面追加then来实现,如:

Future.delayed(Duration(seconds: 1), (){
  int value = 10;
  return value;
}).then((onValue){
  onValue++;
  print('value $onValue');
});

Dart提供了另一个对线程的实现方案:isolate,由线程和独立内存构成,isolate线程之间不共享内存,并且不和主线程的内存堆共享内存,因此不能访问主线程中的变量,或者使用 setState() 来更新 UI。isolate可以很好的利用多核CPU,来进行大量耗时任务的处理。isolate线程之间的通信主要通过port来进行,这个port消息传递的过程是异步的。通过Dart源码也可以看出,实例化一个isolate的过程包括,实例化isolate结构体、在堆中分配线程内存、配置port等过程。

loadData() async {
  ReceivePort receivePort = ReceivePort();
  await Isolate.spawn(dataLoader, receivePort.sendPort);

  // The 'echo' isolate sends its SendPort as the first message
  SendPort sendPort = await receivePort.first;

  List msg = await sendReceive(sendPort, "https://jsonplaceholder.typicode.com/posts");

  setState(() {
    widgets = msg;
  });
}

// The entry point for the isolate
static dataLoader(SendPort sendPort) async {
  // Open the ReceivePort for incoming messages.
  ReceivePort port = ReceivePort();

  // Notify any other isolates what port this isolate listens to.
  sendPort.send(port.sendPort);

  await for (var msg in port) {
    String data = msg[0];
    SendPort replyTo = msg[1];

    String dataURL = data;
    http.Response response = await http.get(dataURL);
    // Lots of JSON to parse
    replyTo.send(json.decode(response.body));
  }
}

Future sendReceive(SendPort port, msg) {
  ReceivePort response = ReceivePort();
  port.send([msg, response.sendPort]);
  return response.first;
}

好了,内容就到这里,以后有更多发现再来补充。若有问题,欢迎指正~
希望与大家共勉!

参考:
https://flutterchina.club/flutter-for-ios/
https://www.jianshu.com/p/54da18ed1a9e

上一篇下一篇

猜你喜欢

热点阅读