【OpenHarmony】Flutter鸿蒙实战:从零打造优雅的网络请求架构与轮播图组件
在现代应用开发中,网络请求是连接前后端的桥梁。本文将带你一步步构建一个结构清晰、可维护性强的网络请求层,并实战实现轮播图数据的获取与展示。
·



在现代应用开发中,网络请求是连接前后端的桥梁。本文将带你一步步构建一个结构清晰、可维护性强的网络请求层,并实战实现轮播图数据的获取与展示。
前言
在开始编码之前,我们需要明确一个优秀的网络请求架构应该具备哪些特性:
- 统一配置管理:基础URL、超时时间等配置集中管理
- 完善的拦截机制:请求与响应拦截,便于统一处理
- 友好的错误处理:HTTP状态码与业务状态码双重校验
- 类型安全的数据模型:强类型转换,避免运行时错误
一、项目准备与依赖配置
1.1 核心依赖引入
首先,我们需要在 pubspec.yaml 中添加强大的网络请求库 —— Dio。
flutter pub add dio
💡 关于Dio:Dio是Flutter社区中最受欢迎的HTTP客户端,支持拦截器、请求取消、文件上传下载、超时设置等丰富功能。
1.2 目标接口分析
本次实战我们将对接以下接口:
| 项目 | 说明 |
|---|---|
| 基础地址 | https://meikou-api.itheima.net |
| 轮播图接口 | /home/banner (GET请求) |
| 成功标识 | code = "1" |
二、架构设计:常量管理
在大型项目中,硬编码的字符串和数字是维护的噩梦。我们首先建立一个统一的常量管理体系。
2.1 目录结构规划
lib/
├── constants/
│ └── index.dart # 全局常量定义
├── utils/
│ └── DioRequest.dart # 网络请求封装
├── api/
│ └── home.dart # 业务API接口
└── viewmodels/
└── home.dart # 数据模型定义
2.2 全局常量定义
文件:lib/constants/index.dart
/// 全局配置常量
class GlobalConstants {
/// API基础地址
static const String BASE_URL = "https://meikou-api.itheima.net/";
/// 请求超时时长(秒)
static const int TIME_OUT = 10;
/// 业务成功状态码
static const String SUCCESS_CODE = "1";
}
/// 接口地址常量
class HttpConstants {
/// 首页轮播图接口
static const String BANNER_LIST = "/home/banner";
}
🔍 设计要点:
- 使用
const修饰符确保编译时常量static修饰实现全局访问,无需实例化- 语义化的命名规范,提升代码可读性
三、核心引擎:网络请求封装
3.1 Dio二次封装架构
文件:lib/utils/DioRequest.dart
import 'package:dio/dio.dart';
import 'package:qing_mall/constants/index.dart';
/// Dio网络请求封装类
class DioRequest {
final Dio _dio = Dio();
/// 构造函数 - 初始化配置
DioRequest() {
// 配置基础选项
_dio.options
..baseUrl = GlobalConstants.BASE_URL
..connectTimeout = Duration(seconds: GlobalConstants.TIME_OUT)
..sendTimeout = Duration(seconds: GlobalConstants.TIME_OUT)
..receiveTimeout = Duration(seconds: GlobalConstants.TIME_OUT);
// 添加拦截器
_addInterceptor();
}
/// 添加请求拦截器
void _addInterceptor() {
_dio.interceptors.add(
InterceptorsWrapper(
// 请求拦截
onRequest: (request, handler) {
// 可在此添加token等通用请求头
handler.next(request);
},
// 响应拦截
onResponse: (response, handler) {
// 校验HTTP状态码 (200-299)
if (response.statusCode! >= 200 && response.statusCode! < 300) {
handler.next(response);
return;
}
handler.reject(DioException(requestOptions: response.requestOptions));
},
// 错误拦截
onError: (error, handler) {
handler.reject(error);
},
),
);
}
/// GET请求方法
Future<dynamic> get(String url, {Map<String, dynamic>? params}) async {
try {
final response = await _dio.get(url, queryParameters: params);
return _handleResponse(response);
} catch (e) {
rethrow;
}
}
/// 响应数据处理 - 校验业务状态码
Future<dynamic> _handleResponse(Response<dynamic> task) async {
try {
final data = task.data as Map<String, dynamic>;
// 业务状态码校验
if (data["code"] == GlobalConstants.SUCCESS_CODE) {
return data["result"]; // 返回实际业务数据
}
// 业务异常抛出
throw Exception(data["message"] ?? "数据加载异常");
} catch (e) {
throw Exception(e);
}
}
}
/// 全局单例对象
final dioRequest = DioRequest();
四、数据模型:类型安全的转换
4.1 轮播图模型定义
文件:lib/viewmodels/home.dart
/// 轮播图数据模型
class BannerItem {
/// 轮播图ID
final String id;
/// 图片URL地址
final String imgUrl;
BannerItem({
required this.id,
required this.imgUrl,
});
/// JSON工厂构造函数 - 实现动态类型到强类型的转换
factory BannerItem.formJSON(Map<String, dynamic> json) {
return BannerItem(
id: json["id"] ?? "",
imgUrl: json["imgUrl"] ?? "",
);
}
}
💡 Flutter类型系统:与JavaScript不同,Flutter是强类型语言,必须显式完成动态类型到对象类型的转换。
五、业务层API封装
5.1 轮播图接口实现
文件:lib/api/home.dart
import 'package:qing_mall/constants/index.dart';
import 'package:qing_mall/utils/DioRequest.dart';
import 'package:qing_mall/viewmodels/home.dart';
/// 获取轮播图列表数据
/// 返回类型安全的BannerItem列表
Future<List<BannerItem>> getBannerListAPI() async {
// 发起网络请求
final response = await dioRequest.get(HttpConstants.BANNER_LIST);
// 数据转换:动态列表 → 强类型列表
return (response as List)
.map((item) => BannerItem.formJSON(item as Map<String, dynamic>))
.toList();
}
六、UI层集成与状态管理
6.1 首页状态管理
文件:lib/pages/Home/index.dart
import 'package:flutter/cupertino.dart';
import 'package:qing_mall/api/home.dart';
import 'package:qing_mall/viewmodels/home.dart';
import 'package:qing_mall/components/Home/HmSlider.dart';
import 'package:qing_mall/components/Home/HmCategory.dart';
import 'package:qing_mall/components/Home/HmSuggestion.dart';
import 'package:qing_mall/components/Home/HmHot.dart';
import 'package:qing_mall/components/Home/HmMoreList.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key});
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
/// 轮播图数据列表
List<BannerItem> _bannerList = [];
void initState() {
super.initState();
_loadBannerData();
}
/// 加载轮播图数据
void _loadBannerData() async {
_bannerList = await getBannerListAPI();
setState(() {}); // 触发UI更新
}
/// 构建滚动视图子组件
List<Widget> _getScrollChildren() {
return [
SliverToBoxAdapter(child: HmSlider(bannerList: _bannerList)),
SliverToBoxAdapter(child: SizedBox(height: 10)),
SliverToBoxAdapter(child: HmCategory()),
SliverToBoxAdapter(child: SizedBox(height: 10)),
SliverToBoxAdapter(child: HmSuggestion()),
SliverToBoxAdapter(child: SizedBox(height: 10)),
SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Flex(
direction: Axis.horizontal,
children: [
Expanded(child: HmHot()),
SizedBox(width: 10),
Expanded(child: HmHot()),
],
),
),
),
SliverToBoxAdapter(child: SizedBox(height: 10)),
HmMorelist(),
];
}
Widget build(BuildContext context) {
return CustomScrollView(slivers: _getScrollChildren());
}
}
6.2 运行效果
最终实现效果:
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)