You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:53:20