Flutter for OpenHarmony:retrofit_generator 自动生成类型安全的 HTTP 客户端代码(Dio 的最佳拍档) 深度解析与鸿蒙适配指南
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

前言
虽然 Dio 已经是 Dart 生态中最好用的网络库,但直接写 dio.get('/user/1') 依然存在硬编码 URL、参数难以验证等问题。在 Java/Kotlin 后端开发中,Retrofit + Annotations 是标准操作。
retrofit_generator 为 Dart 带来了这一能力。它通过注解(如 @GET, @POST, @Body)定义 API 接口,并在编译时自动生成基于 Dio 的请求代码。这不仅让网络层更清晰、更易维护,还能充分利用 Dart 的类型系统。
一、概念介绍/原理解析
1.1 核心概念
- REST Interface: 使用抽象类定义 API 接口。
- Build Runner: 代码生成工具,读取源文件并生成
.g.dart。 - Dio Client: 底层网络执行器,被生成的代码调用。
通过 @GET 等注解配置
运行 build_runner 构建任务
Uses
发出网络请求
API 接口定义 (抽象类)
retrofit_generator 核心引擎
生成的实现类 API.g.dart
Dio 网络执行器
后端远程服务器
1.2 进阶概念
支持文件上传 (@MultiPart)、自定义 Header、以及配合 JSON 序列化库 (json_serializable) 自动转换数据模型。
二、集成与基础用法
2.1 添加依赖
dependencies:retrofit: ^4.0.0 dio: ^5.0.0 json_annotation: ^4.8.0 dev_dependencies:retrofit_generator: ^5.0.0 build_runner: ^2.3.0 json_serializable: ^6.6.0 2.2 定义 API 接口
创建 api_service.dart:
import'package:retrofit/retrofit.dart';import'package:dio/dio.dart';part'api_service.g.dart';// 声明生成文件@RestApi(baseUrl:"https://api.example.com/")abstractclassApiService{factoryApiService(Dio dio,{String baseUrl})= _ApiService;@GET("/tasks")Future<List<Task>>getTasks();// 假设 Task 已定义@POST("/tasks")Future<Task>createTask(@Body()Task task);@DELETE("/tasks/{id}")Future<void>deleteTask(@Path("id")String id);}2.3 生成代码
运行命令:
dart run build_runner build 
三、常见应用场景
3.1 场景 1:CRUD 操作
标准的增删改查 API,参数校验和类型转换全部自动完成。
@GET("/users/{id}")Future<User>getUser(@Path("id") int id);@POST("/users")Future<User>createUser(@Body()User user);@DELETE("/users/{id}")Future<void>deleteUser(@Path("id") int id);3.2 场景 2:文件上传
使用 @MultiPart 和 @Part 注解轻松上传图片。
@POST("/upload")@MultiPart()Future<void>uploadImage(@Part()File file);
3.3 场景 3:查询参数过滤
@Query("status") String? status 自动拼接 URL 参数 ?status=open。
@GET("/tasks")Future<List<Task>>getTasks(@Query("status")String status,@Query("sort")String sortOrder,);
四、OpenHarmony 平台适配
4.1 纯 Dart 实现
生成的是标准 Dart 代码,依赖于 dio。只要 Dio 能跑(OpenHarmony 上 Dio 完美支持),retrofit 就没问题。
4.2 文件上传注意事项
在 OpenHarmony 上获取文件路径(如相册图片)时,需确保拥有读取权限,并将 File 对象正确传递给 Dio。
五、完整示例代码
本示例定义一个简单的用户 API,并在页面中调用。
5.1 数据模型 (User)
import'package:json_annotation/json_annotation.dart';part'user.g.dart';@JsonSerializable()classUser{final int id;finalString name;finalString email;User({required this.id, required this.name, required this.email});factoryUser.fromJson(Map<String,dynamic> json)=> _$UserFromJson(json);Map<String,dynamic>toJson()=> _$UserToJson(this);}5.2 API 定义
// api_client.dartimport'package:retrofit/retrofit.dart';import'package:dio/dio.dart';import'user.dart';part'api_client.g.dart';@RestApi(baseUrl:"https://jsonplaceholder.typicode.com")abstractclassRestClient{factoryRestClient(Dio dio,{String baseUrl})= _RestClient;@GET("/users")Future<List<User>>getUsers();}5.3 页面 UI
import'package:flutter/material.dart';import'package:dio/dio.dart';// 别忘了引入 dioimport'api_client.dart';import'user.dart';voidmain(){runApp(constMaterialApp(home:RetrofitPage()));}classRetrofitPageextendsStatefulWidget{constRetrofitPage({super.key});@overrideState<RetrofitPage>createState()=>_RetrofitPageState();}class _RetrofitPageState extendsState<RetrofitPage>{ late RestClient _client;@overridevoidinitState(){super.initState();final dio =Dio();// 初始化 Dio 实例 _client =RestClient(dio);}@overrideWidgetbuild(BuildContext context){returnScaffold( appBar:AppBar(title:constText('Retrofit Demo')), body:FutureBuilder<List<User>>( future: _client.getUsers(), builder:(context, snapshot){if(snapshot.connectionState ==ConnectionState.waiting){returnconstCenter(child:CircularProgressIndicator());}elseif(snapshot.hasError){returnCenter(child:Text("Error: ${snapshot.error}"));}elseif(snapshot.hasData){final users = snapshot.data!;returnListView.builder( itemCount: users.length, itemBuilder:(context, index){final user = users[index];returnListTile( leading:CircleAvatar(child:Text(user.name[0])), title:Text(user.name), subtitle:Text(user.email),);},);}returnconstCenter(child:Text("No data"));},),);}}
六、总结
retrofit_generator 让网络请求变得像本地函数调用一样简单。它是大型 Flutter 项目必备的架构组件。
最佳实践:
- 统一配置:在全局 Dio 实例中添加 Log 拦截器、Token 拦截器,然后注入给各 API Service。
- 错误处理:虽然 API 返回 Future,但网络异常仍需
try-catch或配合runZonedGuarded处理。 - 模块化:按业务模块拆分多个 API Service 类,避免单一文件过大。