返回

Flutter实战-搭建微信项目(八):异步+多线程的巧妙结合

IOS

在上篇文章中,我们分别介绍了异步编程和多线程编程。本篇内容将带你领略异步 Future 和多线程 compute 强强联手,打造出更强大的应用场景。

异步与多线程的默契配合

先来编写一段代码,直观感受异步和多线程的结合:

import 'dart:async';

main() async {
  // 模拟耗时任务
  Future<String> task1 = Future.delayed(Duration(seconds: 2), () => "task1");

  // 异步任务
  task1.then((value) => print(value));

  // 多线程任务
  var task2 = await compute(calculateSum, 10, 20);
  print(task2);
}

// 多线程计算任务
int calculateSum(int a, int b) {
  print("task2 is running...");
  return a + b;
}

运行结果如下:

task2 is running...
20
task1

可以看到,代码中同时使用了 Future(异步编程)和 compute(多线程编程)。执行顺序与我们的预期不符,compute 任务率先打印结果,而异步任务紧随其后。

解密执行顺序之谜

为何执行顺序与预期不符?原因在于:

  • 异步任务被调度到了微任务队列中。 当异步任务的 then() 方法被调用时,一个新的微任务被添加到微任务队列中。微任务队列优先级高于事件队列,因此当事件循环发现微任务队列中有任务时,它会优先执行微任务。

  • 多线程任务在后台线程中执行。 compute() 方法创建一个新的线程,在该线程中执行任务。主线程和后台线程是并发执行的,因此后台线程执行任务的速度可能比主线程中的微任务更快。

异步+多线程的应用场景

异步和多线程的结合在实际开发中有着广泛的应用:

  • 处理耗时任务。 通过将耗时任务放到后台线程中执行,可以避免主线程卡顿,从而提升用户体验。

  • 并发执行任务。 多线程可以同时执行多个任务,从而提高应用的效率。

  • 异步通知。 可以通过使用 Future 来实现异步通知,当后台线程完成任务时,可以通知主线程进行后续处理。

实战演练

接下来,我们通过一个实战案例来体会异步和多线程的妙用。假设我们有一个需要耗时处理的任务,同时我们希望在任务处理过程中实时更新进度。可以使用异步和多线程来实现:

import 'dart:async';

main() async {
  // 模拟耗时任务
  Future<String> task = Future.delayed(Duration(seconds: 5), () => "task completed");

  // 创建一个 Stream 用于更新进度
  StreamController<int> progressStreamController = StreamController();

  // 在后台线程中执行耗时任务,并更新进度
  compute(runTask, progressStreamController).then((_) => progressStreamController.close());

  // 订阅进度更新
  progressStreamController.stream.listen((progress) {
    print("Progress: $progress%");
  });

  // 当任务完成时,打印结果
  task.then((value) => print(value));
}

// 在后台线程中执行任务
void runTask(StreamController<int> progressStreamController) {
  for (var i = 0; i < 100; i++) {
    // 模拟进度更新
    progressStreamController.add(i);
    // 模拟耗时任务
    Future.delayed(Duration(milliseconds: 100));
  }
}

运行代码,可以看到进度条实时更新,同时任务完成时打印结果。

总结

异步 Future 和多线程 compute 的巧妙结合,为 Flutter 开发提供了更强大的工具集。通过合理的应用,可以有效提升应用性能和用户体验。未来文章中,我们将深入探索异步编程和多线程编程的更多高级用法,敬请期待!