如何在Flutter中使用Dio、Retrofit和Riverpod实现POST API请求?
Flutter中用Dio+Retrofit+Riverpod实现POST请求完整流程
1. 安装依赖
在pubspec.yaml中添加以下依赖:
dependencies: flutter: sdk: flutter dio: ^5.4.0+1 retrofit: ^4.0.3 flutter_riverpod: ^2.4.9 json_annotation: ^4.8.1 dev_dependencies: flutter_test: sdk: flutter build_runner: ^2.4.8 retrofit_generator: ^7.0.8 json_serializable: ^6.7.1
添加后执行flutter pub get安装依赖。
2. 定义数据模型
创建models/login_model.dart,定义请求和响应的实体类,配合json_serializable实现序列化:
import 'package:json_annotation/json_annotation.dart'; part 'login_model.g.dart'; @JsonSerializable() class LoginRequest { final String username; final String password; LoginRequest({required this.username, required this.password}); factory LoginRequest.fromJson(Map<String, dynamic> json) => _$LoginRequestFromJson(json); Map<String, dynamic> toJson() => _$LoginRequestToJson(this); } @JsonSerializable() class LoginResponse { final String token; final String userId; LoginResponse({required this.token, required this.userId}); factory LoginResponse.fromJson(Map<String, dynamic> json) => _$LoginResponseFromJson(json); Map<String, dynamic> toJson() => _$LoginResponseToJson(this); }
执行命令生成序列化代码:
flutter pub run build_runner build
3. 定义Retrofit API接口
创建services/api_service.dart,定义POST请求接口:
import 'package:dio/dio.dart'; import 'package:retrofit/retrofit.dart'; import '../models/login_model.dart'; part 'api_service.g.dart'; @RestApi(baseUrl: "https://your-api-base-url.com/") abstract class ApiService { factory ApiService(Dio dio) = _ApiService; @POST("auth/login") Future<LoginResponse> login(@Body() LoginRequest request); }
再次执行flutter pub run build_runner build生成Retrofit实现代码。
4. Riverpod状态管理
创建providers/auth_provider.dart,封装API实例和登录状态逻辑:
import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../services/api_service.dart'; import '../models/login_model.dart'; // 提供ApiService实例 final apiServiceProvider = Provider<ApiService>((ref) { final dio = Dio(); // 可添加拦截器、超时配置等 dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); return ApiService(dio); }); // 登录状态枚举 enum LoginState { initial, loading, success, error } // 登录状态管理Notifier class LoginNotifier extends StateNotifier<({LoginState state, String? message, LoginResponse? data})> { final ApiService apiService; LoginNotifier(this.apiService) : super((state: LoginState.initial, message: null, data: null)); Future<void> login(String username, String password) async { state = (state: LoginState.loading, message: null, data: null); try { final response = await apiService.login(LoginRequest(username: username, password: password)); state = (state: LoginState.success, message: "登录成功", data: response); } on DioException catch (e) { state = (state: LoginState.error, message: e.response?.data?["message"] ?? "登录失败", data: null); } catch (e) { state = (state: LoginState.error, message: "未知错误", data: null); } } } // 提供LoginNotifier实例 final loginNotifierProvider = StateNotifierProvider<LoginNotifier, ({LoginState state, String? message, LoginResponse? data})>((ref) { return LoginNotifier(ref.watch(apiServiceProvider)); });
5. UI层实现
创建pages/login_page.dart,实现登录页面并调用逻辑:
import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/auth_provider.dart'; class LoginPage extends ConsumerStatefulWidget { const LoginPage({super.key}); @override ConsumerState<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends ConsumerState<LoginPage> { final _usernameController = TextEditingController(); final _passwordController = TextEditingController(); @override void dispose() { _usernameController.dispose(); _passwordController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final loginState = ref.watch(loginNotifierProvider); return Scaffold( appBar: AppBar(title: const Text("登录")), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ TextField( controller: _usernameController, decoration: const InputDecoration(labelText: "用户名"), ), TextField( controller: _passwordController, decoration: const InputDecoration(labelText: "密码"), obscureText: true, ), const SizedBox(height: 20), if (loginState.state == LoginState.loading) const CircularProgressIndicator() else ElevatedButton( onPressed: () { ref.read(loginNotifierProvider.notifier).login( _usernameController.text.trim(), _passwordController.text.trim(), ); }, child: const Text("登录"), ), if (loginState.message != null) Padding( padding: const EdgeInsets.only(top: 16), child: Text( loginState.message!, style: TextStyle(color: loginState.state == LoginState.success ? Colors.green : Colors.red), ), ), ], ), ), ); } }
关键说明
- Retrofit通过注解生成API实现代码,简化Dio的调用逻辑
- Riverpod的StateNotifier负责处理异步请求的状态变化(加载、成功、失败)
- UI层通过
Consumer监听状态变化,动态更新界面
内容的提问来源于stack exchange,提问作者chinmay chauhan
相关产品推荐
相关产品推荐

