在这里插入图片描述

✨“俺はモンキー・D・ルフィ。海贼王になる男だ!”

在这里插入图片描述


在这里插入图片描述

在现代应用开发中,网络请求是连接前后端的桥梁。本文将带你一步步构建一个结构清晰、可维护性强的网络请求层,并实战实现轮播图数据的获取与展示。


前言

在开始编码之前,我们需要明确一个优秀的网络请求架构应该具备哪些特性:

  • 统一配置管理:基础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

Logo

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

更多推荐