欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.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'; // 声明生成文件

(baseUrl: "https://api.example.com/")
abstract class ApiService {
  factory ApiService(Dio dio, {String baseUrl}) = _ApiService;

  ("/tasks")
  Future<List<Task>> getTasks(); // 假设 Task 已定义

  ("/tasks")
  Future<Task> createTask(() Task task);

  ("/tasks/{id}")
  Future<void> deleteTask(("id") String id);
}

2.3 生成代码

运行命令:

dart run build_runner build

在这里插入图片描述

三、常见应用场景

3.1 场景 1:CRUD 操作

标准的增删改查 API,参数校验和类型转换全部自动完成。

("/users/{id}")
Future<User> getUser(("id") int id);

("/users")
Future<User> createUser(() User user);

("/users/{id}")
Future<void> deleteUser(("id") int id);

3.2 场景 2:文件上传

使用 @MultiPart@Part 注解轻松上传图片。

("/upload")
()
Future<void> uploadImage(() File file);

在这里插入图片描述

3.3 场景 3:查询参数过滤

@Query("status") String? status 自动拼接 URL 参数 ?status=open

("/tasks")
Future<List<Task>> getTasks(
  ("status") String status,
  ("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';

()
class User {
  final int id;
  final String name;
  final String email;

  User({required this.id, required this.name, required this.email});

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

5.2 API 定义

// api_client.dart
import 'package:retrofit/retrofit.dart';
import 'package:dio/dio.dart';
import 'user.dart';

part 'api_client.g.dart';

(baseUrl: "https://jsonplaceholder.typicode.com")
abstract class RestClient {
  factory RestClient(Dio dio, {String baseUrl}) = _RestClient;

  ("/users")
  Future<List<User>> getUsers();
}

5.3 页面 UI

import 'package:flutter/material.dart';
import 'package:dio/dio.dart'; // 别忘了引入 dio
import 'api_client.dart';
import 'user.dart';

void main() {
  runApp(const MaterialApp(home: RetrofitPage()));
}

class RetrofitPage extends StatefulWidget {
  const RetrofitPage({super.key});

  
  State<RetrofitPage> createState() => _RetrofitPageState();
}

class _RetrofitPageState extends State<RetrofitPage> {
  late RestClient _client;
  
  
  void initState() {
    super.initState();
    final dio = Dio(); // 初始化 Dio 实例
    _client = RestClient(dio);
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Retrofit Demo')),
      body: FutureBuilder<List<User>>(
        future: _client.getUsers(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text("Error: ${snapshot.error}"));
          } else if (snapshot.hasData) {
            final users = snapshot.data!;
            return ListView.builder(
              itemCount: users.length,
              itemBuilder: (context, index) {
                final user = users[index];
                return ListTile(
                  leading: CircleAvatar(child: Text(user.name[0])),
                  title: Text(user.name),
                  subtitle: Text(user.email),
                );
              },
            );
          }
          return const Center(child: Text("No data"));
        },
      ),
    );
  }
}

在这里插入图片描述

六、总结

retrofit_generator 让网络请求变得像本地函数调用一样简单。它是大型 Flutter 项目必备的架构组件。

最佳实践

  1. 统一配置:在全局 Dio 实例中添加 Log 拦截器、Token 拦截器,然后注入给各 API Service。
  2. 错误处理:虽然 API 返回 Future,但网络异常仍需 try-catch 或配合 runZonedGuarded 处理。
  3. 模块化:按业务模块拆分多个 API Service 类,避免单一文件过大。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐