Flutter中调用API及多API串联传参实现方案咨询
实现步骤与代码示例
首先,你的需求核心是API B的调用依赖于API A选中的下拉框值,所以不能像你现在这样用两个独立的FutureBuilder并行请求。我们需要用StatefulWidget来维护选中状态,只有当用户选择了API A的选项后,才触发API B的请求。
具体实现思路:
- 用
StatefulWidget保存三个关键状态:- API A返回的下拉选项数据
- 用户选中的下拉框值
- API B的请求Future(选中值变化时更新这个Future)
- 先通过
FutureBuilder加载API A的数据,渲染下拉框 - 当下拉框选项改变时,更新选中值,并发起API B的请求
- 再用另一个
FutureBuilder根据API B的请求状态展示结果
完整代码示例:
import 'package:flutter/material.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; // 假设API A返回的是包含id和名称的列表(比如城市列表) class ApiAData { final String id; final String name; ApiAData({required this.id, required this.name}); factory ApiAData.fromJson(Map<String, dynamic> json) { return ApiAData( id: json['id'], name: json['name'], ); } } // 假设API B返回的是选中项对应的关联数据(比如城市景点列表) class ApiBData { final String id; final String title; ApiBData({required this.id, required this.title}); factory ApiBData.fromJson(Map<String, dynamic> json) { return ApiBData( id: json['id'], title: json['title'], ); } } class ApiChainExample extends StatefulWidget { const ApiChainExample({super.key}); @override State<ApiChainExample> createState() => _ApiChainExampleState(); } class _ApiChainExampleState extends State<ApiChainExample> { // API A的请求Future,页面初始化时触发 late Future<List<ApiAData>> _apiAFuture; // 用户选中的API A数据项 ApiAData? _selectedItem; // API B的请求Future,选中值变化后才赋值 Future<List<ApiBData>>? _apiBFuture; @override void initState() { super.initState(); // 页面加载时先请求API A获取下拉选项 _apiAFuture = _fetchApiA(); } // 请求API A的函数 Future<List<ApiAData>> _fetchApiA() async { final response = await http.get(Uri.parse('你的API A地址')); if (response.statusCode == 200) { List<dynamic> data = json.decode(response.body); return data.map((item) => ApiAData.fromJson(item)).toList(); } else { throw Exception('加载API A数据失败'); } } // 请求API B的函数,参数为API A选中项的id Future<List<ApiBData>> _fetchApiB(String paramId) async { final response = await http.get(Uri.parse('你的API B地址?param=$paramId')); if (response.statusCode == 200) { List<dynamic> data = json.decode(response.body); return data.map((item) => ApiBData.fromJson(item)).toList(); } else { throw Exception('加载API B数据失败'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('API联动示例')), body: SafeArea( child: Form( child: ListView( padding: const EdgeInsets.all(16), children: [ // 加载API A数据并渲染下拉框 FutureBuilder<List<ApiAData>>( future: _apiAFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } else if (snapshot.hasError) { return Text('错误:${snapshot.error}'); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Text('API A无数据'); } else { return DropdownButtonFormField<ApiAData>( value: _selectedItem, hint: const Text('请选择一项'), items: snapshot.data!.map((item) { return DropdownMenuItem<ApiAData>( value: item, child: Text(item.name), ); }).toList(), onChanged: (ApiAData? newValue) { setState(() { _selectedItem = newValue; // 选中值变化时,发起API B请求 if (newValue != null) { _apiBFuture = _fetchApiB(newValue.id); } else { _apiBFuture = null; } }); }, ); } }, ), const SizedBox(height: 20), // 加载并展示API B的数据 if (_apiBFuture != null) FutureBuilder<List<ApiBData>>( future: _apiBFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } else if (snapshot.hasError) { return Text('错误:${snapshot.error}'); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Text('API B无数据'); } else { return ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: snapshot.data!.length, itemBuilder: (context, index) { final item = snapshot.data![index]; return ListTile( title: Text(item.title), subtitle: Text(item.id), ); }, ); } }, ), ], ), ), ), ); } }
关键细节说明:
- 用
initState初始化API A的请求,保证页面加载时就开始获取下拉选项 DropdownButtonFormField的onChanged回调是核心逻辑:选中新值后更新状态,并触发API B的请求- API B的
FutureBuilder只在_apiBFuture不为null时渲染,避免初始状态下的空请求 - 处理了加载中、错误、无数据等多种状态,提升用户体验
内容的提问来源于stack exchange,提问作者shilpa navale
相关产品推荐
相关产品推荐

