Flutter & Riverpod:如何在Provider中使用.when方法
问题解决:The method when isn't defined for the type Future
错误原因
你直接调用了bluetoothServiceProvider.notifier.discoverDevices(),这个方法返回的是Future<List<Device>>类型,而.when()是Riverpod中AsyncValue类的专属方法,因此会出现该错误。正确的做法是让Provider维护异步操作的状态,通过监听Provider的状态来使用.when()处理加载、成功、错误场景。
修改后的服务类代码
part 'bluetooth_manager.g.dart'; @riverpod class BluetoothService extends _$BluetoothService { @override AsyncValue<List<Device>> build() { // 初始状态设为空数据,可根据需求改为加载中 return const AsyncValue.data([]); } Future<void> discoverDevices() async { try { // 更新状态为加载中 state = const AsyncValue.loading(); // 模拟设备扫描逻辑,替换为实际蓝牙扫描代码 await Future.delayed(const Duration(seconds: 5)); final devices = <Device>[/* 扫描得到的设备列表 */]; // 更新状态为成功数据 state = AsyncValue.data(devices); } catch (error, stacktrace) { // 更新状态为错误 state = AsyncValue.error(error, stacktrace); } } }
修改后的视图层代码
class ModulesView extends ConsumerStatefulWidget { const ModulesView({Key? key}) : super(key: key); @override ConsumerState<ModulesView> createState() => _ModulesViewState(); } class _ModulesViewState extends ConsumerState<ModulesView> { @override void initState() { super.initState(); // 在页面初始化后触发设备扫描,也可改为按钮点击触发 WidgetsBinding.instance.addPostFrameCallback((_) { ref.read(bluetoothServiceProvider.notifier).discoverDevices(); }); } @override Widget build(BuildContext context, WidgetRef ref) { // 监听Provider的状态,获取AsyncValue对象 final bluetoothState = ref.watch(bluetoothServiceProvider); return Scaffold( body: Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: bluetoothState.when( data: (data) => modulesFound(ref, data), loading: () => loading(), error: (error, stacktrace) => ErrorView( errorMessage: error.toString(), retryFunction: () => ref.read(bluetoothServiceProvider.notifier).discoverDevices(), ), ), ), ); } }
核心调整说明
- 服务类
build()方法返回AsyncValue<List<Device>>,用于维护异步操作的三种状态:加载中、成功、错误。 discoverDevices()不再直接返回Future,而是通过更新Provider的state来同步状态变化,让视图层可以监听。- 视图层通过
ref.watch(bluetoothServiceProvider)获取AsyncValue实例,此时即可正常调用.when()方法处理不同状态。 - 扫描触发逻辑移至
initState(或按钮点击事件),避免build方法重复执行扫描操作。
内容的提问来源于stack exchange,提问作者Naografix
相关产品推荐
相关产品推荐

