繁体   English   中英

为什么 Riverpod 提供商在已经有价值的情况下进入加载 state?

[英]Why Riverpod provider goes into the loading state when there's already value?

最小可重现代码:

class FooPage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final asyncValue = ref.watch(provider1);
    print('loading: ${asyncValue.isLoading}, value: ${asyncValue.valueOrNull}');
    return Container();
  }
}

final provider1 = StreamProvider<int>((ref) {
  final stream = ref.watch(provider2);
  return stream.maybeWhen(
    orElse: () => Stream.value(0),
    data: (x) {
      print('data = $x');
      return Stream.value(x);
    },
  );
});

final provider2 = StreamProvider<int>((ref) async* {
  await Future.delayed(Duration(seconds: 3));
  yield 1;
});

Output:

flutter: loading: true, value: null // Why value != 0
flutter: loading: false, value: 0
// After 3 seconds...
flutter: data = 1
flutter: loading: true, value: 0 // Why value != 1 
flutter: loading: false, value: 1

有两个问题。

  1. 当我已经在orElse回调中提供了默认值时,为什么第一行不打印该值而不是加载 state 并打印null

  2. 一旦我在 3 秒后获得数据,为什么提供者会打印loading: true, value: 0

首次创建StreamProvider时,它还没有从 stream 接收到任何数据,因此它的isLoading属性将为true ,其valueOrNull属性将为null 这就是 output 的第一行打印 loading: loading: true, value: null的原因。

一旦 stream 发出数据, StreamProvider将使用 stream 中的最新值更新其valueOrNull属性。但是, ConsumerWidget可能尚未重建以反映此更改。 ConsumerWidget重建时,它将从 stream 接收最新值并打印它。 这就是 output 的第四行打印loading: false, value: 1的原因。

orElse回调用于在 stream 尚未发出任何数据时为StreamProvider提供默认值。 StreamProvider接收到stream的数据后,不会影响StreamProvider 。这就是为什么output第二行和第五行打印loading: false, value: 0的原因。

综上所述, StreamProvider最初会在加载 state 并有一个null的值,直到它从 stream 接收到数据。一旦它接收到数据,它会更新它的值以反映来自 stream 的最新值,但是这个更新可能不会反映在ConsumerWidget中,直到它重建。 orElse回调仅在 stream 未发出任何数据时为StreamProvider提供默认值。

provider2改变了(它从加载到拥有数据)。 由于provider1依赖于它,因此provider1被重新计算。

这最终创建了一个新的 stream。然后提供者监听新的 stream。监听 stream 是一个异步操作,因此对于一个框架, provider1 1 无法访问 stream 公开的新值。因此,你得到了一个加载state。

这应该不是问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM