Future 成功完成,但数据功能从未执行
Future finish succesfully, but data function never executed
这段代码有问题,但我不知道是什么。
问题是 loading
被执行,Future 成功完成并打印 "From the onPress",但是 data
函数从未执行所以永远不要打印 "Done from the button!!!"
这是重现问题的示例:
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
为 return 类型,结果相同:
final userUpdateFutureProvider = FutureProvider.autoDispose.family<User, User>((ref, user) async {
return Future.delayed(Duration(seconds: 100), () => user);
});
创建后 ticket 认为这是一个错误,作者反应非常快。
基本上,他的回复是:
This is not how AsyncValue works. when does not "listen" to
data/loading/error. It's a switch-case on the current state.
所以用下一个新代码替换 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"));
},
所以解决方案看起来是使用内部 future 来注册回调。
我不清楚的是为什么相同的代码在 onPressed 之外工作?
这是一个完整的工作示例:https://github.com/angelcervera/testing_riverpod/blob/main/lib/main_onpress_working.dart
这段代码有问题,但我不知道是什么。
问题是 loading
被执行,Future 成功完成并打印 "From the onPress",但是 data
函数从未执行所以永远不要打印 "Done from the button!!!"
这是重现问题的示例:
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
为 return 类型,结果相同:
final userUpdateFutureProvider = FutureProvider.autoDispose.family<User, User>((ref, user) async {
return Future.delayed(Duration(seconds: 100), () => user);
});
创建后 ticket 认为这是一个错误,作者反应非常快。
基本上,他的回复是:
This is not how AsyncValue works. when does not "listen" to data/loading/error. It's a switch-case on the current state.
所以用下一个新代码替换 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"));
},
所以解决方案看起来是使用内部 future 来注册回调。
我不清楚的是为什么相同的代码在 onPressed 之外工作?
这是一个完整的工作示例:https://github.com/angelcervera/testing_riverpod/blob/main/lib/main_onpress_working.dart