一、前置准备
1.1 步骤
(1)安装 dio
(2)定义常量数据、基础地址、超时时间、业务状态、请求地址
(3)封装网络请求工具,基础地址,拦截器
(4)请求工具进一步解构,处理 http 状态和业务状态
(5)类工厂转化动态类型到对象类型
(6)封装请求 API 调用工厂函数
(7)初始化数据更新状态
1.2 接口请求成功示例
接口基础地址:https://meikou-api.itheima.net
轮播图地址(get):https://meikou-api.itheima.net/home/banner
请求轮播图成功返回的数据:

1.3 dio使用方法
Dart
flutter pub add dio

二、轮播图API请求实现
2.1 编写常量类
首先先修改文件夹的名字,因为我之前写错了,这个文件夹用于放置常量。

lib/constants/index.dart代码
为什么要用static修饰?因为:
(1)非静态每个实例都会创建新的内存。
(2)可以全局访问,无需创建对象。
(3)这些配置在应用生命周期内不会改变。
Dart
//全局状态
class GlobalConstants {
//基础地址
static String BASE_URL = "https://meikou-api.itheima.net/";
//超时时间
static int TIME_OUT = 10;
//成功状态
static String SUCCESS_CODE = "1";
}
但是以上代码叫作变量,而我们是不需要改变的,所以加上"const"关键字,变为常量
Dart
//全局状态
class GlobalConstants {
//基础地址
static const String BASE_URL = "https://meikou-api.itheima.net/";
//超时时间
static const int TIME_OUT = 10;
//成功状态
static const String SUCCESS_CODE = "1";
}
完整代码:
Dart
//全局状态
class GlobalConstants {
//基础地址
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";
}
2.2 封装请求类
在lib/utils文件夹下新建一个DioRequest.dart进行Dio网络请求的封装。
DioRequest.dart代码
Dart
//基于Dio进行二次封装
import 'package:dio/dio.dart';
import 'package:qing_mall/constants/index.dart';
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) {
handler.next(request);
}, onResponse: (response, handler) {
//http状态码 200 300
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 {
Response<dynamic> res = await task;
final data = res.data as Map<String, dynamic>; //data才是我们真实的接口返回的数据
if (data["code"] == GlobalConstants.SUCCESS_CODE) {
//如果等于1 才认定http状态和业务状态均为正常 就可以正常的放行通过
return data["result"]; //只要result结果
}
//抛出异常
throw Exception(data["message"] ?? "加载数据异常");
} catch (e) {
throw Exception(e);
}
}
}
// 单例对象
final dioRequest = DioRequest();
//dio请求工具发出请求->返回的数据通过Response<dynamic>.data
//把所有的接口的data解放出来 拿到真正的数据 要判断业务状态码是不是等于1
2.3 转换动态类型
修改lib/viewmodels/home.dart代码
home.dart代码
Dart
class BannerItem {
String id;
String imgUrl;
BannerItem({required this.id, required this.imgUrl});
//扩展一个工厂函数 一般用factory来声明 一般用来创建实例对象
factory BannerItem.formJSON(Map<String, dynamic> json) {
//必须返回一个BannerItem对象
return BannerItem(id: json["id"] ?? "", imgUrl: json["imgUrl"] ?? "");
}
}
//每一个轮播图具体类型
//flutter必须强制转换,没有隐式转化
2.4 封装API
在lib/api/目录下新建home.dart,目的是返回业务所需要的数据结构。
完整代码:
Dart
//封装一个api 目的是返回业务侧要的数据结构
import 'package:qing_mall/constants/index.dart';
import 'package:qing_mall/utils/DioRequest.dart';
import 'package:qing_mall/viewmodels/home.dart';
Future<List<BannerItem>> getBannerListAPI() async {
//返回请求
final tt =
((await dioRequest.get(HttpConstants.BANNER_LIST)) as List).map((item) {
return BannerItem.formJSON(item as Map<String, dynamic>);
}).toList();
return tt;
}
修改lib/pages/Home/index.dart代码
完整代码:
Dart
import 'package:flutter/cupertino.dart';
import 'package:qing_mall/api/home.dart';
import 'package:qing_mall/components/Home/HmCategory.dart';
import 'package:qing_mall/components/Home/HmHot.dart';
import 'package:qing_mall/components/Home/HmMoreList.dart';
import 'package:qing_mall/components/Home/HmSlider.dart';
import 'package:qing_mall/components/Home/HmSuggestion.dart';
import 'package:qing_mall/viewmodels/home.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key});
@override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
List<BannerItem> _bannerList = [
// BannerItem(
// id: "1",
// imgUrl: "https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/meituan/1.jpg",
// ),
// BannerItem(
// id: "2",
// imgUrl: "https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/meituan/2.png",
// ),
// BannerItem(
// id: "3",
// imgUrl: "https://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/meituan/3.jpg",
// ),
];
//获取滚动容器的内容
List<Widget> _getScrollChildren() {
return [
//包裹普通widget的sliver家族的组件内容
SliverToBoxAdapter(child: HmSlider(bannerList: _bannerList)), //轮播图组件
//放置分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//SliverGrid SliverList指南纵向排列
SliverToBoxAdapter(child: HmCategory()), //分类组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
SliverToBoxAdapter(child: HmSuggestion()), //推荐组件
SliverToBoxAdapter(child: SizedBox(height: 10)),
//Flex和Expanded配合起来可以均分比例
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(), //无限滚动列表
];
}
@override
void initState() {
// TODO: implement initState
super.initState();
_getBannederList();
}
void _getBannederList() async {
_bannerList = await getBannerListAPI();
setState(() {});
}
@override
Widget build(BuildContext context) {
//CustomScrollview要求:必须是sliver家族的内容
return CustomScrollView(slivers: _getScrollChildren());
}
}
以上步骤全部完成后,运行鸿蒙的模拟器,会得到如图所示效果,请求了真实的API接口

三、提交代码
3.1 git可视化提交代码
最后,别忘了提交代码哦。这次我们改用Android Studio的可视化进行git的提交。
选中该图标,如果没有,可能是已经没有装git的插件。



3.2 总结
感谢大家的观看,本项目的地址是:https://AtomGit.com/Deng666/shangcheng.git。如果在文章中复刻遇到问题,可到代码托管仓库克隆一份源码。如果本篇文章对你有帮助,请你点个赞吧!~
最后,欢迎加入开源鸿蒙跨平台社区: