干货分享:一文掌握HarmonyOS Next网络请求开发 原创 精华
全栈若城
发布于 2025-8-19 15:08
浏览
2收藏
@toc
前言
大家好,我是若城。本系列旨在帮助开发者快速实现HarmonyOS Next应用中的常用功能,提供即拿即用的代码示例。本文将重点介绍网络请求的封装与应用,让开发者能够轻松实现API接口调用。本系列不会过多讲解基础知识,需要申请权限的部分请开发者自行处理。
功能概述
本文将详细介绍:
- HTTP请求基础方法的封装
- 实用的HTTP请求工具类设计
- 类型定义与接口规范
- 实际应用场景演示
通过这些内容,开发者可以快速构建自己的网络请求层,并进行二次开发以满足项目需求, 好了,废话不多说,我们开始上课.
Request 工具类实现
文件位置
将以下代码保存为Request.ets
,放置在项目的utils目录下:
核心代码
下面是封装好的
Request.ets
代码可以直接拿走哦~~~
import { http } from '@kit.NetworkKit'
import { promptAction, router } from '@kit.ArkUI'
// 常量定义
export const TOKEN_KEY: string = 'token'
export const BASE_URL: string = 'xxxxxx' // 你的接口地址
/**
* API响应数据结构
*/
export class ResponsesData<T> {
code: number = 0
msg: string = ""
data: T | null = null
}
interface EmptyInterface {}
/**
* HTTP请求基础方法
* @param url 请求路径
* @param method 请求方法
* @param data 请求参数
* @returns Promise<T>
*/
async function requestHttp<T>(url: string = '', method: http.RequestMethod = http.RequestMethod.GET, data?: object): Promise<T> {
// 创建HTTP请求实例
const httpRequest = http.createHttp()
// 拼接完整URL
let urlStr = BASE_URL + url
// GET请求参数处理
if (method === http.RequestMethod.GET) {
if (data && Object.keys(data).length) {
const queryParams = Object.keys(data)
.filter(key => data[key] !== undefined && data[key] !== null)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
.join('&')
if (queryParams) {
urlStr += "?" + queryParams
}
}
}
// 请求配置
const config: http.HttpRequestOptions = {
method,
readTimeout: 10000,
// GET请求不需要传递extraData
extraData: method === http.RequestMethod.GET ? '' : data || {} as EmptyInterface,
header: {
'Content-Type': 'application/json',
"Authorization": AppStorage.get(TOKEN_KEY) as string || ''
}
}
try {
// 发送请求
const res = await httpRequest.request(urlStr, config)
console.info(`[HTTP ${method}] ${urlStr}`)
// 处理HTTP状态码
switch (res.responseCode) {
case 401:
// 处理认证失败
AppStorage.set<string>(TOKEN_KEY, '')
promptAction.showToast({ message: 'token超时!' })
router.replaceUrl({ url: 'pages/Login/LoginPage' })
return Promise.reject(new Error('token超时!'))
case 404:
promptAction.showToast({ message: '请求地址不正确!' })
return Promise.reject(new Error('请求地址不正确!'))
default:
// 解析响应数据
const result = JSON.parse(res.result as string) as ResponsesData<T>
if (result.code === 200) {
return result.data as T
} else {
promptAction.showToast({ message: result.msg || '服务器异常!' })
return Promise.reject(new Error(result.msg))
}
}
} catch (error) {
promptAction.showToast({ message: `请求失败: ${error}` })
return Promise.reject(error)
} finally {
// 释放资源
httpRequest.destroy()
}
}
/**
* HTTP请求工具类
*/
export class Request {
/**
* GET请求
* @param url 请求路径
* @param data 请求参数
*/
static get<T>(url: string, data?: object): Promise<T> {
return requestHttp<T>(url, http.RequestMethod.GET, data)
}
/**
* POST请求
* @param url 请求路径
* @param data 请求体
*/
static post<T>(url: string, data?: object): Promise<T> {
return requestHttp<T>(url, http.RequestMethod.POST, data)
}
/**
* PUT请求
* @param url 请求路径
* @param data 请求体
*/
static put<T>(url: string, data?: object): Promise<T> {
return requestHttp<T>(url, http.RequestMethod.PUT, data)
}
/**
* DELETE请求
* @param url 请求路径
* @param data 请求参数
*/
static delete<T>(url: string, data?: object): Promise<T> {
return requestHttp<T>(url, http.RequestMethod.DELETE, data)
}
}
数据类型定义
为了更好地管理数据结构,我们创建一个types.ets
文件来定义接口类型:
// 食物分类接口
export interface Category {
name: string;
icon: Resource;
}
// 食物数据接口
export interface FoodItem {
name: string;
img: string;
calory: string;
}
// 常用食物数据接口
export interface CommonFood {
category: string;
name: string;
img: string;
calory: string;
}
// 接口返回数据
export interface ResponseData {
keyword: string;
Lists: FoodItem[]
}
实战应用
在页面中使用网络请求
首先,导入必要的模块:
import { FoodItem, ResponseData } from '../utils/types';
import { Request } from "../utils/request"
然后,实现搜索功能:
// 搜索功能
searchFood(keyword: string): void {
Request.get<ResponseData>(`?key=xxxxxxx&food=${keyword}`).then(res => {
console.log('搜索结果', JSON.stringify(res))
this.searchResults = res.Lists
router.pushUrl({
url: "pages/SearchResult",
params: res.Lists
})
})
}
注意: 首页的页面代码以及相关内容可以参考上一节的文章哦,这里就不做展示啦~~
搜索结果页面实现
import { FoodItem, ResponseData } from '../utils/types';
import { router, Router } from '@kit.ArkUI';
@Entry
@Component
struct SearchResult {
@State message: string = 'Hello World';
@State searchResults: FoodItem[] = []
aboutToAppear(): void {
const params = router.getParams() as FoodItem[]
console.log("结果页", JSON.stringify(params))
this.searchResults = params
}
build() {
// 展示搜索结果
List() {
ForEach(this.searchResults, (item: FoodItem) => {
ListItem() {
this.FoodItem(item)
}
})
}
.width('100%')
.layoutWeight(1)
.listDirection(Axis.Vertical)
.edgeEffect(EdgeEffect.Spring)
.padding({ top: 8, bottom: 16 })
.backgroundColor('#F8F8F8')
}
@Builder
FoodItem(item: FoodItem) {
Column() {
Row() {
Image(item.img)
.width(80)
.height(80)
.borderRadius(12)
.backgroundColor('#F0F0F0')
.margin({ right: 16 })
.objectFit(ImageFit.Cover)
.alt($r('app.media.food'))
Column() {
Text(item.name)
.fontSize(18)
.fontWeight(FontWeight.Medium)
.margin({ bottom: 8 })
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
}
.width('100%')
.padding(16)
}
.backgroundColor(Color.White)
.borderRadius(16)
.shadow({ radius: 8, color: 'rgba(0, 0, 0, 0.08)', offsetY: 2 })
.margin({ bottom: 12, left: 16, right: 16 })
}
}
效果展示
首页
搜索结果页
总结
本文介绍了如何在HarmonyOS Next应用中封装HTTP请求工具类,并通过实际案例展示了其使用方法。通过这种封装,我们可以大大简化网络请求的实现,提高代码的可维护性和可扩展性。希望这篇文章对你的HarmonyOS Next应用开发有所帮助!下课~~
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
赞
3
收藏 2
回复
相关推荐
代码逻辑清晰明了,可以直接拿来用了,解决了新项目封装的问题,太棒啦!
感谢d l z c
大佬威武
感谢大佬支持
感谢大佬分享,可以直接使用!