Riverpod3 注解方式写api 请求的provider在其他地方调用方式
在 View (UI 页面) 中的使用方式
在 UI 中,你可以直接使用 ref.watch 拿到的 AsyncValue。AsyncValue 提供了强大的 .when() 模式匹配,让你非常优雅地处理 Loading、Error 和 Data 状态。
class DeviceDetailView extends ConsumerWidget {
final String deviceId;
const DeviceDetailView({super.key, required this.deviceId});
@override
Widget build(BuildContext context, WidgetRef ref) {
// 1. 获取异步状态 AsyncValue<DeviceItemModel>
final deviceDetailAsync = ref.watch(deviceDetailProvider(deviceId));
// 2. 获取 Notifier 实例(用来调用 updateName、refresh 等逻辑方法)
final notifier = ref.read(deviceDetailProvider(deviceId).notifier);
return Scaffold(
// 3. 使用 .when 响应不同加载阶段
body: deviceDetailAsync.when(
// 数据加载成功
data: (device) => Column(
children: [
Text('设备名称: ${device.deviceName}'),
Text('在线状态: ${device.isOnline ? '在线' : '离线'}'),
ElevatedButton(
onPressed: () => notifier.updateName('新设备名字'),
child: const Text('修改名称'),
),
],
),
// 正在加载中(骨架屏/转圈)
loading: () => const Center(child: CircularProgressIndicator()),
// 加载报错
error: (err, stack) => Center(
child: Text('加载失败: $err'),
),
),
);
}
}
在其他 Provider 中的使用方式
在其他的 Notifier 或 Provider 内部使用时,主要分为 3 种典型场景:
场景 A:只想“监听”数据变化并同步(最常用)
如果你在另一个 Provider 中需要感知 api 的变更(例如设备名字变了,设置页也要跟着刷新); 当前方式不会阻塞UI渲染
@riverpod
class Setting extends _$Setting {
@override
SettingState build(String deviceId) {
// ref.watch 返回的是 AsyncValue<DeviceItemModel>
final deviceDetailAsync = ref.watch(deviceDetailProvider(deviceId));
// 使用 .value 从包装盒中提出最新的数据实体,可能为null
final device = deviceDetailAsync.value;
return SettingState(
deviceName: device?.deviceName ?? '默认名称',
isOnline: device?.isOnline ?? false,
);
}
}
场景 B:异步链式依赖(等待它彻底加载完成后再做下一步)
如果你在当前 Provider 中需要严格等待 DeviceDetail 从网络/接口加载出来,再发起自己的请求:
@riverpod
Future<List<CameraStream>> cameraStreams(Ref ref, String deviceId) async {
// 🌟 使用 .future!它会返回真正的 Future<DeviceItemModel>
// 会一直 await 阻塞直到 DeviceDetail 的 build() 真正返回成功数据
final device = await ref.watch(deviceDetailProvider(deviceId).future);
// 拿到真正的 device 实体后,再发起属于自己的请求
final streams = await fetchStreamsBySn(device.snNumber);
return streams;
}
场景 C:在某个 Action(方法/按钮点击)中临时触发读取
如果不是在 build 阶段,而是在某个点击方法内部去主动触发或读取最新的设备数据
@riverpod
class ActionController extends _$ActionController {
@override
void build() {}
Future<void> handleSomeClick(String deviceId) async {
// 方式 1:如果确定只需要当前内存里已有的值
final currentDevice = ref.read(deviceDetailProvider(deviceId)).valueOrNull;
// 方式 2:如果不确定数据是否已加载完成,想确保拿到最新的(未完成就等待请求完成)
final latestDevice = await ref.read(deviceDetailProvider(deviceId).future);
// 方式 3:直接调用 DeviceDetail 的方法(如刷新)
await ref.read(deviceDetailProvider(deviceId).notifier).refresh();
}
}
博客中所涉及到的图片都有版权,请谨慎使用

浙公网安备 33010602011771号