如何使用Riverpod在同一页面高效调用多个关联API(附示例)
使用Riverpod处理依赖式多API调用示例
核心思路
利用Riverpod的Provider依赖特性,让后续API调用自动等待前置API完成并获取结果,无需手动管理异步流程的状态和触发逻辑。
步骤1:定义API服务类
先模拟两个存在依赖关系的API接口,第二个接口需要第一个接口返回的参数:
class ApiService { // 模拟第一个API:获取用户ID Future<String> fetchUserId() async { await Future.delayed(const Duration(seconds: 1)); return "user_123"; } // 模拟第二个API:依赖用户ID获取用户详情 Future<Map<String, dynamic>> fetchUserDetails(String userId) async { await Future.delayed(const Duration(seconds: 1)); return { "id": userId, "name": "John Doe", "email": "john@example.com" }; } }
步骤2:用Riverpod定义依赖式Provider
通过Provider串联API调用,让第二个Provider自动依赖第一个的结果:
import 'package:flutter_riverpod/flutter_riverpod.dart'; // 提供ApiService实例的基础Provider final apiServiceProvider = Provider<ApiService>((ref) => ApiService()); // 第一个API调用:获取用户ID的FutureProvider final userIdProvider = FutureProvider<String>((ref) { final apiService = ref.watch(apiServiceProvider); return apiService.fetchUserId(); }); // 第二个API调用:依赖userIdProvider结果的FutureProvider final userDetailsProvider = FutureProvider<Map<String, dynamic>>((ref) { // 监听userIdProvider的状态,自动等待其完成 final userIdState = ref.watch(userIdProvider); // 如果userId还未获取到,抛出异常让Riverpod自动重试 if (userIdState.isLoading) throw StateError("Waiting for user ID"); if (userIdState.hasError) throw userIdState.error!; final userId = userIdState.value!; final apiService = ref.watch(apiServiceProvider); return apiService.fetchUserDetails(userId); });
步骤3:在页面中消费Provider
通过ConsumerWidget监听Provider状态,处理加载、错误、成功三种场景:
class MultiApiPage extends ConsumerWidget { const MultiApiPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final userIdState = ref.watch(userIdProvider); final userDetailsState = ref.watch(userDetailsProvider); return Scaffold( appBar: AppBar(title: const Text("依赖式API调用")), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 渲染第一个API的状态 userIdState.when( loading: () => const CircularProgressIndicator(), error: (err, stack) => Text("获取用户ID失败:$err"), data: (userId) => Text("用户ID:$userId"), ), const SizedBox(height: 20), // 渲染第二个API的状态 userDetailsState.when( loading: () => const CircularProgressIndicator(), error: (err, stack) => Text("获取用户详情失败:$err"), data: (details) => Column( children: [ Text("用户名:${details['name']}"), Text("邮箱:${details['email']}"), ], ), ), ], ), ), ); } }
关键优化点
- 自动状态流转:当
userIdProvider的状态从加载变为成功时,userDetailsProvider会自动触发调用,无需手动监听回调。 - 错误联动:如果第一个API调用失败,第二个API会直接进入错误状态,避免无效调用。
- 缓存复用:Riverpod默认缓存FutureProvider的结果,除非手动调用
ref.refresh()或Provider被销毁,减少重复请求。
内容的提问来源于stack exchange,提问作者Atul maurya
相关产品推荐
相关产品推荐

