![](/img/trans.png)
[英]riverpod, my provider's state keeps on loading, instead of actually displaying data
[英]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
有两个问题。
当我已经在orElse
回调中提供了默认值时,为什么第一行不打印该值而不是加载 state 并打印null
。
一旦我在 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.