Flutter网络请求实战:Retrofit+Dio完美解决方案

Flutter网络请求:Retrofit使用指南

Retrofit是Android平台上广受欢迎的HTTP客户端库,在Flutter中可以通过retrofit包实现类似的网络请求功能。下面是完整的使用指南:

1. 添加依赖

首先在pubspec.yaml中添加所需依赖:

yaml 复制代码
dependencies:
  retrofit: ^4.0.1
  dio: ^5.3.2
  json_annotation: ^4.8.1

dev_dependencies:
  retrofit_generator: ^4.0.1
  build_runner: ^2.4.4

2. 创建API接口

定义一个抽象类来描述你的API接口:

dart 复制代码
import 'package:retrofit/retrofit.dart';
import 'package:dio/dio.dart';
import 'package:json_annotation/json_annotation.dart';

part 'api_service.g.dart';

@RestApi(baseUrl: "https://jsonplaceholder.typicode.com/")
abstract class ApiService {
  factory ApiService(Dio dio, {String baseUrl}) = _ApiService;

  @GET("/posts")
  Future<List<Post>> getPosts();

  @GET("/posts/{id}")
  Future<Post> getPost(@Path("id") int id);

  @POST("/posts")
  Future<Post> createPost(@Body() Post post);
}

@JsonSerializable()
class Post {
  final int id;
  final String title;
  final String body;
  final int userId;

  Post({
    required this.id,
    required this.title,
    required this.body,
    required this.userId,
  });

  factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
  Map<String, dynamic> toJson() => _$PostToJson(this);
}

3. 生成代码

运行以下命令生成实现代码:

bash 复制代码
flutter pub run build_runner build

这会生成api_service.g.dart文件。

4. 使用API服务

dart 复制代码
void main() async {
  final dio = Dio();
  final apiService = ApiService(dio);

  try {
    // 获取所有帖子
    final posts = await apiService.getPosts();
    print(posts);

    // 获取单个帖子
    final post = await apiService.getPost(1);
    print(post);

    // 创建新帖子
    final newPost = await apiService.createPost(
      Post(id: 101, title: 'New Post', body: 'Content', userId: 1),
    );
    print(newPost);
  } catch (e) {
    print(e);
  }
}

5. 高级功能

添加请求头

dart 复制代码
@GET("/posts")
@Headers({'Content-Type': 'application/json'})
Future<List<Post>> getPosts();

查询参数

dart 复制代码
@GET("/posts")
Future<List<Post>> getPostsByUser(@Query("userId") int userId);

表单数据

dart 复制代码
@POST("/login")
@FormUrlEncoded()
Future<User> login(
  @Field("username") String username,
  @Field("password") String password,
);

拦截器

dart 复制代码
final dio = Dio()
  ..interceptors.add(
    InterceptorsWrapper(
      onRequest: (options, handler) {
        // 添加认证token
        options.headers['Authorization'] = 'Bearer token';
        return handler.next(options);
      },
      onError: (DioError e, handler) {
        // 错误处理
        return handler.next(e);
      },
    ),
  );

6. 完整配置示例

dart 复制代码
import 'package:dio/dio.dart';
import 'package:retrofit/retrofit.dart';

part 'api_service.g.dart';

@RestApi(baseUrl: "https://api.example.com/v1/")
abstract class ApiService {
  factory ApiService(Dio dio, {String baseUrl}) {
    dio.options = BaseOptions(
      receiveTimeout: const Duration(seconds: 30),
      connectTimeout: const Duration(seconds: 30),
    );
    
    return _ApiService(dio, baseUrl: baseUrl);
  }

  @GET("users")
  Future<List<User>> getUsers();

  @GET("users/{id}")
  Future<User> getUser(@Path("id") String id);

  @POST("users")
  Future<User> createUser(@Body() User user);

  @PUT("users/{id}")
  Future<User> updateUser(@Path("id") String id, @Body() User user);

  @DELETE("users/{id}")
  Future<void> deleteUser(@Path("id") String id);
}

7. 错误处理

dart 复制代码
try {
  final response = await apiService.getUser('123');
} on DioError catch (e) {
  if (e.response != null) {
    print(e.response?.statusCode);
    print(e.response?.data);
  } else {
    print(e.message);
  }
}

8. 测试API服务

dart 复制代码
test('getPosts returns List<Post>', () async {
  final dio = DioAdapterMock();
  final apiService = ApiService(dio);

  when(dio.get('/posts')).thenAnswer((_) async => Response(
    data: [
      {'id': 1, 'title': 'Test', 'body': 'Content', 'userId': 1}
    ],
    statusCode: 200,
    requestOptions: RequestOptions(path: '/posts'),
  ));

  final posts = await apiService.getPosts();
  expect(posts, isA<List<Post>>());
  expect(posts.first.title, 'Test');
});

Retrofit为Flutter提供了类型安全的HTTP客户端实现,通过代码生成简化了网络请求的编写,同时保持了Dio的强大功能。

相关推荐
程序员Ctrl喵15 小时前
异步编程:Event Loop 与 Isolate 的深层博弈
开发语言·flutter
前端不太难16 小时前
Flutter 如何设计可长期维护的模块边界?
flutter
小蜜蜂嗡嗡17 小时前
flutter列表中实现置顶动画
flutter
始持18 小时前
第十二讲 风格与主题统一
前端·flutter
始持18 小时前
第十一讲 界面导航与路由管理
flutter·vibecoding
始持18 小时前
第十三讲 异步操作与异步构建
前端·flutter
新镜18 小时前
【Flutter】 视频视频源横向、竖向问题
flutter
黄林晴19 小时前
Compose Multiplatform 1.10 发布:统一 Preview、Navigation 3、Hot Reload 三箭齐发
android·flutter
Swift社区19 小时前
Flutter 应该按功能拆,还是按技术层拆?
flutter
肠胃炎20 小时前
树形选择器组件封装
前端·flutter