likes
comments
collection
share

Flutter Package推荐:async。非dart:async,而是对其的扩展。

作者站长头像
站长
· 阅读数 3

当我们在用dart编程的时候,经常会用到内置SDK的异步功(dart:async)能用于处理流数据。这篇文章是推荐一个异步包(package:async),它包含了许多有用的附加功能。

AsyncCache

运行异步函数并将结果缓存一段时间。

这个类的主要作用是处理那些可能涉及昂贵操作(如文件输入/输出、网络访问或独立计算)的代码模式。这些操作不太可能频繁变动,且运行次数相对较少。通过引入这个类,我们可以更有效地管理和优化这些操作,提高程序的性能和稳定性。

例如:

final _usersCache = new AsyncCache<List<String>>(const Duration(hours: 1));

///1小时内多次请求就会跳过后面的数据请求。
Future<List<String>> get onlineUsers => _usersCache.fetch(() {
  // ...
});

AsyncMemoizer

AsyncMemoizer 类用于确保异步函数只执行一次,并缓存其结果。

当某个函数可能多次运行以获取其结果,但实际上只需要运行一次即可达到目的时,可以使用 AsyncMemoizer。为了缓存异步函数的结果,你可以在函数外部创建一个 memoizer(例如,如果你想要缓存一个方法的结果,可以将其作为实例字段),然后在函数体内调用 runOnce 方法。

这对于像 close() 和需要执行异步工作的 getter 这样的方法非常有用。

例如:

class SomeResource {
  final _closeMemo = AsyncMemoizer();

  Future close() => _closeMemo.runOnce(() {
    // ...
  });
}

CancelableOperation

CancelableOperation 类表示一个可以取消的异步操作。配合CancelableCompleter使用。

这个操作的结果值通过 value 属性暴露出来。当这个操作被取消时,value 既不会成功完成,也不会因为错误而完成。如果 value 已经完成了(无论是成功还是失败),那么取消操作将不会产生任何效果。

// 定义一个单元测试,名称为'fires valueOrCancellation with the given value'  
test('fires valueOrCancellation with the given value', () {  
  // 创建一个CancelableCompleter实例,用于处理int类型的异步操作  
  var completer = CancelableCompleter<int>();  
   
  expect(completer.operation.valueOrCancellation(1), completion(equals(1)));  
  
  // 取消completer的操作。
  completer.operation.cancel();  
  
  // 结束单元测试  
});

StreamGroup<T> 

StreamGroup<T> 类是对多个流的集合进行封装,它将这些流的事件统一并通过一个中心流发送。

无论是错误事件还是数据事件,都会被转发至这个中心流。这个组中的流在中心流有监听器之前是不会被监听的。这意味着,如果组内的流是广播流,那么它们发出的事件在中心流有监听器之前将会被丢弃。

如果通过 StreamGroup.new 方法构造 StreamGroup,那么中心流将是单订阅的。这种情况下,如果中心流被暂停或取消订阅,组内的所有流也将相应地被暂停或取消订阅。

如果通过 StreamGroup.broadcast 方法构造 StreamGroup,那么中心流将是广播流。在这种情况下,组内的流永远不会被暂停,而组内的单订阅流也永远不会被取消订阅。但需要注意的是,广播组中的单订阅流在添加监听器后又移除监听器时可能会丢弃事件。一旦中心流没有监听器,组内的广播流将被取消订阅;当中心流再次有监听器时,这些广播流将再次被监听。

StreamGroup.merge([
    aStreamOfData,
    anotherStream,
    yetOneMoreStream,
])

StreamQueue

StreamQueue 类是一个基于异步拉取(pull-based)的接口,用于访问流事件。 它封装了一个流,并使得单个事件能够按需获取,而不是在事件到达时立即推送它们。

你可以请求(并保留)流中的一个或多个事件,在所有之前的请求被满足之后,流事件将用来满足你的请求。

例如,如果你请求接下来的两个事件,返回的 Future 对象将由流中接下来两个未被请求的事件来完成。

当没有活跃的请求时,流的订阅将被暂停。

一些流,包括广播流,在暂停时会缓存事件,因此如果请求之间的等待时间过长,可能会导致其他地方的内存膨胀。

这与 StreamIterator 类似,但使用起来更加方便。StreamIterator 要求你手动检查何时有新的事件可用,并且你只能访问该事件的值,直到你检查下一个事件。而 StreamQueue 允许你一次请求多个事件,可以单独请求,也可以使用 take 或 skip 以组的形式请求,或者任意组合请求。

你还可以请求将流的其余部分作为新流提供。这允许你,例如,从流中取出第一个事件,并继续使用流的其余部分作为流。

例如:

var events = StreamQueue<String>(someStreamOfLines);
var first = await events.next;
while (first.startsWith('#')) {
  first = await events.next;
}

if (first.startsWith(MAGIC_MARKER)) {
  var headerCount =
      first.parseInt(first.substring(MAGIC_MARKER.length + 1));
  handleMessage(headers: await events.take(headerCount),
                body: events.rest);
  return;
}

当你不再需要事件时,应该使用 cancel 方法关闭 StreamQueue,这将释放底层的流订阅。


package:async还有其他有用的api,可以提供其他更加有效的异步处理。

Package地址:pub-web.flutter-io.cn/packages/as…