问题描述
这段代码有问题,但我不知道是什么。
问题是 loading
被执行,Future 成功完成并打印 “From the onPress”,但是 data
函数从未执行所以永远不会打印 “通过按钮完成!!!”
这是一个重现问题的示例:
import 'package:Flutter/material.dart';
import 'package:Flutter_riverpod/Flutter_riverpod.dart';
void main() {
runApp(ProviderScope(child: MaterialApp(home: Scaffold(body: Center(child: MyHomeAsyncValue()),))));
}
final voidFutureProvider = FutureProvider.autodispose.family<void,String>((ref,str) {
return Future.delayed(Duration(seconds: 5),() { print(str); });
});
class MyHomeAsyncValue extends ConsumerWidget {
MyHomeAsyncValue({Key? key,}) : super(key: key);
@override
Widget build(BuildContext context,ScopedReader watch) {
return ElevatedButton(
child: Text('Call'),onpressed: () {
final AsyncValue<void> fromButton = context.read(voidFutureProvider("From the onPress"));
fromButton.when(
data: (value) => print("Done from the button!!!"),loading: () => print("Loading...."),error: (error,stackTrace) => print("Error $error"),);
},);
}
}
注意:我尝试将按钮包裹在 Consumer
中并使用 watch
而不是 read
,但结果是一样的。
版本 Flutter_riverpod: ^0.14.0+3
更新:
还测试了避免 void
作为返回类型,结果相同:
final userUpdateFutureProvider = FutureProvider.autodispose.family<User,User>((ref,user) async {
return Future.delayed(Duration(seconds: 100),() => user);
});
更新:创建了一张票 https://github.com/rrousselGit/river_pod/issues/628
解决方法
创建一个 ticket 后认为它是一个错误,作者反应非常快。
基本上,他的回答是:
这不是 AsyncValue 的工作方式。什么时候不“听” 数据/加载/错误。这是当前状态的开关案例。
因此用下一个新代码替换 onPressed 代码有效:
onPressed: () {
final value = context.read(voidFutureProvider("From the onPress").future);
value
.then((value) => print("Done from the button!!!"))
.onError((error,stackTrace) => print("Error $error"));
},
因此该解决方案希望使用内部未来来注册回调。
我不清楚的是为什么相同的代码可以在 onPressed 之外工作? ?
这是一个完整的工作示例:https://github.com/angelcervera/testing_riverpod/blob/main/lib/main_onpress_working.dart