边玩边学鸿蒙影视App开发之网络请求与数据交互 #跟着猫哥学鸿蒙
课程地址:https://blog.csdn.net/yyz_1987/article/details/153418477
在移动应用开发中,网络请求是连接应用与后端服务的重要桥梁。鸿蒙应用也不例外,无论是获取数据、提交用户信息还是进行实时通信,都需要通过网络请求来实现。在"爱影家"APP中,我们需要通过网络请求获取电影列表、电影详情、视频播放地址等信息,这些数据是应用运行的核心。
本章将详细介绍鸿蒙应用中的网络请求相关知识,包括HTTP协议基础、鸿蒙官方网络组件的使用以及第三方库axios的集成,帮助开发者掌握鸿蒙应用中的数据交互技术。
二、HTTP协议基础
1. HTTP协议概述
HTTP(超文本传输协议)是客户端与服务器之间进行通信的一种协议。在鸿蒙应用开发中,我们主要通过HTTP协议与服务器进行数据交互。HTTP请求本质上是客户端向服务器发出请求的过程,而服务器则根据请求返回相应的响应。
2. HTTP请求的基本组成
一个完整的HTTP请求包含以下几个部分:
2.1 请求方法
常见的HTTP请求方法包括:
- GET:请求获取服务器上的资源
- POST:向服务器提交数据,可能会创建新资源或修改现有资源
- PUT:上传文件或更新资源
- DELETE:请求服务器删除指定资源
- OPTIONS:获取目标资源支持的HTTP方法
- HEAD:类似于GET,但只返回响应头,不返回响应体
- PATCH:对资源进行部分修改
在"爱影家"APP中,我们主要使用GET和POST方法获取电影数据。
2.2 URL
URL(统一资源定位符)用于指定要访问的资源地址,也可以理解为向服务器请求资源的API接口。URL通常包含协议、域名、端口号、路径和查询参数等部分。
2.3 请求头
请求头包含了一些附加信息,如用户代理、内容类型、认证信息等。这些信息帮助服务器更好地理解和处理请求。
2.4 请求体
请求体主要用于承载客户端向服务器发送的数据,如表单数据、JSON数据等。在POST、PUT等请求中,请求体尤为重要。
3. HTTP响应的基本组成
HTTP响应主要包含以下部分:
3.1 状态码
状态码表示服务器对请求的处理结果,常见的状态码包括:
- 200 OK:请求成功
- 400 Bad Request:请求参数错误
- 401 Unauthorized:未授权
- 403 Forbidden:禁止访问
- 404 Not Found:请求的资源不存在
- 500 Internal Server Error:服务器内部错误
3.2 响应头
响应头包含了服务器返回的附加信息,如内容类型、缓存控制等。
3.3 响应体
响应体是服务器返回的核心数据,通常以JSON、XML等格式存在。在鸿蒙应用中,我们主要处理JSON格式的响应数据。
三、鸿蒙官方网络组件
1. Network Kit介绍
鸿蒙系统提供了Network Kit(网络服务),主要用于进行HTTP数据请求、WebSocket连接、Socket连接以及网络连接管理等。Network Kit对应的系统API模块为@ohos.net.http,现在已归类到@kit.NetworkKit包中。
2. 权限配置
在使用网络服务之前,需要在应用的配置文件中声明相应的权限:
// module.json5
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
}
]
}
}
这些权限分别用于允许应用访问互联网和获取设备网络信息。
3. 基本使用步骤
使用Network Kit发送HTTP请求的基本步骤如下:
3.1 导入模块
import { http } from '@kit.NetworkKit';
3.2 创建HTTP请求任务
let httpRequest = http.createHttp();
3.3 发起网络请求
httpRequest.request(
'https://api.example.com/movies',
{
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json'
},
expectDataType: http.HttpDataType.STRING
},
(err, data) => {
if (!err) {
// 处理成功响应
console.log('Result:', data.result);
console.log('Status Code:', data.responseCode);
// 解析JSON数据
const jsonData = JSON.parse(data.result as string);
this.handleMovieList(jsonData);
} else {
// 处理错误
console.error('Error:', err);
}
// 及时销毁请求任务
httpRequest.destroy();
}
);
3.4 使用Promise方式
除了回调方式外,Network Kit也支持Promise方式的异步操作:
async function fetchData() {
let httpRequest = http.createHttp();
try {
const data = await httpRequest.request(
'https://api.example.com/movies',
{
method: http.RequestMethod.GET
}
);
console.log('Result:', data.result);
return JSON.parse(data.result as string);
} catch (err) {
console.error('Error:', err);
throw err;
} finally {
httpRequest.destroy();
}
}
四、第三方库axios的使用
1. axios简介
axios是一个流行的HTTP客户端库,用于发送HTTP请求。在鸿蒙应用开发中,我们可以使用适配鸿蒙系统的axios三方库(如nutpi/axios),它提供了更简洁、更强大的API,使得网络请求的处理更加便捷。
2. axios的优势
相比于直接使用官方Network Kit,axios具有以下优势:
- 更简洁的API:链式调用使得代码更易读、易写
- 自动转换JSON数据:自动处理请求和响应的JSON转换
- 拦截器支持:可以在请求发送前和响应接收后进行拦截处理
- 请求取消:支持取消正在进行的请求
- 错误处理:提供更完善的错误处理机制
- 请求/响应转换:可以对请求和响应数据进行转换处理
3. axios的基本使用
3.1 安装与导入
首先需要在项目中添加axios依赖,然后导入使用:
import axios from '@nutpi/axios';
3.2 创建axios实例
创建一个配置了基础URL、超时等参数的axios实例:
const axiosClient = axios.create({
baseURL: 'http://120.27.146.247:8000/api/v1',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
});
3.3 发送GET请求
async function getMovieList() {
try {
const response = await axiosClient.get('/movies');
return response.data;
} catch (error) {
console.error('Failed to get movie list:', error);
throw error;
}
}
3.4 发送POST请求
在"爱影家"APP中,获取电影详情使用的是POST请求:
export const getDetailMv = (id: string): Promise<DetailMvResp> => {
return axiosClient.post({
url: '/detailmovie',
data: { id: id }
});
};
// 调用示例
async function fetchMovieDetail(movieId: string) {
try {
const detailData = await getDetailMv(movieId);
this.detailData = detailData;
} catch (error) {
console.error('Failed to fetch movie detail:', error);
// 显示错误提示
}
}
4. 拦截器的使用
拦截器是axios的一个强大特性,它允许我们在请求发送前和响应接收后执行一些操作。
4.1 请求拦截器
axiosClient.interceptors.request.use(
config => {
// 在发送请求之前做些什么,如添加token
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
// 处理请求错误
return Promise.reject(error);
}
);
4.2 响应拦截器
axiosClient.interceptors.response.use(
response => {
// 对响应数据做点什么
return response.data;
},
error => {
// 处理响应错误
if (error.response) {
// 服务器返回了错误状态码
switch (error.response.status) {
case 401:
// 未授权,处理登录逻辑
handleUnauthorized();
break;
case 404:
// 资源不存在
showToast('请求的资源不存在');
break;
case 500:
// 服务器错误
showToast('服务器错误,请稍后重试');
break;
default:
showToast(`请求失败: ${error.response.status}`);
}
} else if (error.request) {
// 请求已发出,但没有收到响应
showToast('网络连接失败,请检查网络');
} else {
// 请求配置出错
showToast('请求配置错误');
}
return Promise.reject(error);
}
);
五、数据模型定义与管理
1. 定义数据模型
为了更好地管理从服务器获取的数据,我们需要定义清晰的数据模型。在TypeScript中,我们可以使用接口(Interface)来定义数据模型。
// 电影详情响应接口
export interface DetailMvResp {
id: string;
title: string;
images: string;
year: string;
genre: string;
wish_count: number;
rating: number;
summary: string;
casts: DetailMvRespCast[];
// 其他字段...
}
// 影人信息接口
export interface DetailMvRespCast {
id: string;
name: string;
avatar: string;
role: string;
}
// 电影视频源响应接口
export interface MvSourceResp {
sources: string[];
// 其他字段...
}
2. 数据状态管理
在鸿蒙应用中,我们可以使用@State装饰器来管理组件的状态数据。当状态数据发生变化时,UI会自动更新。
@Component
struct DetailPage {
@State detailData: DetailMvResp | null = null;
@State srcData: MvSourceResp | null = null;
@State isLoading: boolean = false;
async onPageShow() {
this.isLoading = true;
try {
// 并行请求电影详情和视频源
const [detailResult, srcResult] = await Promise.all([
getDetailMv(this.movieId),
getMovieSrc(this.movieId)
]);
this.detailData = detailResult;
this.srcData = srcResult;
} catch (error) {
console.error('Failed to load data:', error);
} finally {
this.isLoading = false;
}
}
build() {
// UI渲染
}
}
六、网络请求的最佳实践
1. 错误处理
完善的错误处理是网络请求的重要部分,它可以提升用户体验,避免应用崩溃。
async function safeFetch<T>(fetchFn: () => Promise<T>): Promise<T | null> {
try {
const result = await fetchFn();
return result;
} catch (error) {
console.error('Network error:', error);
// 显示用户友好的错误提示
promptAction.showToast({
message: '网络请求失败,请稍后重试',
duration: 2000
});
return null;
}
}
// 使用示例
const movieList = await safeFetch(() => getMovieList());
if (movieList) {
// 处理数据
} else {
// 处理失败情况
}
2. 缓存策略
合理的缓存策略可以减少不必要的网络请求,提升应用性能和用户体验。
// 简单的内存缓存
class CacheManager {
private cache: Map<string, { data: any; timestamp: number }> = new Map();
private maxAge: number = 5 * 60 * 1000; // 5分钟
set(key: string, data: any): void {
this.cache.set(key, {
data,
timestamp: Date.now()
});
}
get(key: string): any | null {
const cached = this.cache.get(key);
if (!cached) return null;
// 检查缓存是否过期
if (Date.now() - cached.timestamp > this.maxAge) {
this.cache.delete(key);
return null;
}
return cached.data;
}
clear(): void {
this.cache.clear();
}
}
const cacheManager = new CacheManager();
// 在网络请求中使用缓存
async function getMovieListWithCache(): Promise<MovieList> {
const cacheKey = 'movie_list';
// 尝试从缓存获取
const cachedData = cacheManager.get(cacheKey);
if (cachedData) {
return cachedData;
}
// 缓存未命中,发起网络请求
const data = await getMovieList();
// 更新缓存
cacheManager.set(cacheKey, data);
return data;
}
3. 请求节流与防抖
对于频繁触发的请求(如搜索功能),使用节流或防抖技术可以减少请求次数,提升性能。
// 防抖函数
function debounce<T extends (...args: any[]) => any>(
func: T,
wait: number
): (...args: Parameters<T>) => void {
let timeout: number | null = null;
return function(...args: Parameters<T>) {
if (timeout !== null) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
func.apply(this, args);
}, wait);
};
}
// 在搜索功能中使用防抖
@Component
struct SearchPage {
@State searchText: string = '';
// 创建防抖的搜索函数
private debouncedSearch = debounce((text: string) => {
this.performSearch(text);
}, 500);
onSearchChange(event: TextInputChangeEvent) {
this.searchText = event.text;
this.debouncedSearch(this.searchText);
}
async performSearch(keyword: string) {
if (keyword.trim().length > 0) {
try {
const results = await searchMovies(keyword);
// 处理搜索结果
} catch (error) {
console.error('Search failed:', error);
}
}
}
}
4. 批量请求处理
对于需要同时发起多个请求的场景,可以使用Promise.all来并行处理,提高效率。
async function loadMovieDetails(movieIds: string[]) {
try {
// 创建所有请求的Promise数组
const promises = movieIds.map(id => getDetailMv(id));
// 并行执行所有请求
const results = await Promise.all(promises);
// 处理所有结果
return results;
} catch (error) {
console.error('Failed to load movie details:', error);
throw error;
}
}
七、总结
网络请求是鸿蒙应用开发中不可或缺的一部分。通过本文的介绍,我们了解了HTTP协议基础、鸿蒙官方Network Kit的使用以及第三方库axios的集成,这些知识对于构建功能完整的鸿蒙应用至关重要。
在实际开发中,我们需要根据具体需求选择合适的网络请求方式,同时注重错误处理、性能优化和用户体验。通过合理使用拦截器、缓存策略、防抖节流等技术,我们可以构建出高效、稳定的网络交互模块。
更多推荐


所有评论(0)