HarmonyOS 窥探网络请求
作者:访客发布时间:2023-12-26分类:程序开发学习浏览:97
介绍
HarmonyOS 平台中使用网络请求,需要引入 "@ohos.net.http", 并且需要在 module.json5 文件中申请网络权限, 即 “ohos.permission.INTERNET”
本篇文章将尝试使用 @ohos.net.http 来实现网络请求
场景设定
- 网络请求主页面,包含两部分:a. 实验内容 b. 网络请求加载动画
- 简单封装网络请求,包含三部分:a. 异步 b. 同步 c. 自定义装饰器传参
场景主页面
- WeiBo UniDemo HuaWei : 请求顺序
- WeiBo1 UniDemo2 HuaWei3 : 异步/同步请求时,序号表示请求回来的顺序
- “开始网络请求-异步” : 开始异步请求
- “开始网络请求-同步” : 开始同步请求
- “开始网络请求-自定义方法装饰器” : 采用自定义方法装饰器进行传参,进而完成网络请求
官方网络请求案例
注意:
每次请求都必须新创建一个HTTP请求实例,即只要发起请求,必须调用createHttp方法
官方指南
API手册
关于 @ohos.net.http 有三个request方法
-
request(url: string, callback: AsyncCallback): void;
1.1 如下“官方指南代码缩减版”使用到了这个方法 -
request(url: string, options: HttpRequestOptions, callback: AsyncCallback): void;
2.1 如下“官方指南代码” 使用了这个方法 -
request(url: string, options?: HttpRequestOptions): Promise;
3.1 将在后续实践代码中使用到
// 引入包名
import http from '@ohos.net.http';
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
// 用于订阅HTTP响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息
// 从API 8开始,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)。 8+
httpRequest.on('headersReceive', (header) => {
console.info('header: ' + JSON.stringify(header));
});
httpRequest.request(
// 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
"EXAMPLE_URL",
{
method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET
// 开发者根据自身业务需要添加header字段
header: {
'Content-Type': 'application/json'
},
// 当使用POST请求时此字段用于传递内容
extraData: {
"data": "data to send",
},
expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型
usingCache: true, // 可选,默认为true
priority: 1, // 可选,默认为1
connectTimeout: 60000, // 可选,默认为60000ms
readTimeout: 60000, // 可选,默认为60000ms
usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定
}, (err, data) => {
if (!err) {
// data.result为HTTP响应内容,可根据业务需要进行解析
console.info('Result:' + JSON.stringify(data.result));
console.info('code:' + JSON.stringify(data.responseCode));
// data.header为HTTP响应头,可根据业务需要进行解析
console.info('header:' + JSON.stringify(data.header));
console.info('cookies:' + JSON.stringify(data.cookies)); // 8+
} else {
console.info('error:' + JSON.stringify(err));
// 取消订阅HTTP响应头事件
httpRequest.off('headersReceive');
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}
}
);
// 引入包名
import http from '@ohos.net.http';
// 每一个httpRequest对应一个HTTP请求任务,不可复用
let httpRequest = http.createHttp();
httpRequest.request(
// 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
"EXAMPLE_URL",
(err, data) => {
if (!err) {
// data.result为HTTP响应内容,可根据业务需要进行解析
console.info('Result:' + JSON.stringify(data.result));
console.info('code:' + JSON.stringify(data.responseCode));
// data.header为HTTP响应头,可根据业务需要进行解析
console.info('header:' + JSON.stringify(data.header));
console.info('cookies:' + JSON.stringify(data.cookies)); // 8+
} else {
console.info('error:' + JSON.stringify(err));
// 取消订阅HTTP响应头事件
httpRequest.off('headersReceive');
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}
}
);
场景布局
基础页面组件代码
考虑到实际的场景会用到网络请求加载,因此这里将发挥 @BuilderParam 装饰器作用,先定义基础页面
组件中定义了 @Prop netLoad:boolean 变量来控制是否展示加载动画
@Component
export struct BasePage {
@Prop netLoad: boolean
//指向一个组件
@BuilderParam aB0: () => {}
build(){
Stack(){
//为组件占位
this.aB0()
if (this.netLoad) {
LoadingProgress()
.width(px2vp(150))
.height(px2vp(150))
.color(Color.Blue)
}
}.hitTestBehavior(HitTestMode.None)
}
}
主页面布局代码
import { BasePage } from './BasePage'
@Entry
@Component
struct NetIndex {
@State netLoad: number = 0
@State msg: string = ''
build() {
Stack(){
BasePage({netLoad: this.netLoad != 0}) {
Column( {space: 20} ){
Row({space: 20}){
Text('WeiBo').fontColor(Color.Black)
Text('UniDemo').fontColor(Color.Black)
Text('HuaWei').fontColor(Color.Black)
}
Row({space: 20}){
Text('WeiBo' + this.weiboIndex)
Text('UniDemo' + this.uniIndex)
Text('HuaWei' + this.huaweiIndex)
}
Button('开始网络请求 - 异步').fontSize(20).onClick( () => {
...
})
Button('开始网络请求 - 同步').fontSize(20).onClick( () => {
...
})
Button('开始网络请求-自定义方法装饰器').fontSize(20).onClick( () => {
...
})
Scroll() {
Text(this.msg).width('100%')
}
.scrollable(ScrollDirection.Vertical)
}
.width('100%')
.height('100%')
.padding({top: px2vp(120)})
}
}
}
}
简单装封装网络请求
函数传参,直接调用封装方法
网络请求样例
WeiBo为数据结构体,暂时不用关心,后续会贴出完整代码,这里仅仅是演示网络请求用法
//引用封装好的HNet网络工具类
import HNet from './util/HNet'
@State msg: string = ''
getWeiBoData(){
HNet.get<WeiBo>({
url: 'https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188',
}).then( (r) => {
this.msg = ''
if(r.code == 0 && r.result){
r.result.data.statuses.forEach((value: WeiBoItem) => {
this.msg = this.msg.concat(value.created_at + ' ' + value.id + '\n')
})
} else {
this.msg = r.code + ' ' + r.msg
}
console.log('顺序-weibo-' + (new Date().getTime() - starTime))
this.netLoad--
})
}
自定义方法装饰器,完成传参调用
网络请求样例
NetController.getWeiBo<WeiBo>().then( r => {
......
})
按照业务定义传参
import { Get, NetResponse } from './util/HNet'
export default class BizNetController {
@Get('https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188')
static getWeiBo<WeiBo>(): Promise<NetResponse<WeiBo>>{ return }
}
封装的网络请求代码
import http from '@ohos.net.http';
//自定义网络请求参数对象
class NetParams{
url: string
extraData?: JSON
}
//自定义数据公共结构体
export class NetResponse<T> {
result: T
code: number
msg: string
}
//网络封装工具类
class HNet {
//POST 请求方法
static post<T>(options: NetParams): Promise<NetResponse<T>>{
return this.request(options, http.RequestMethod.POST)
}
//GET 请求方法
static get<T>(options: NetParams): Promise<NetResponse<T>>{
return this.request(options, http.RequestMethod.GET)
}
private static request<T>(options: NetParams, method: http.RequestMethod): Promise<NetResponse<T>>{
let r = http.createHttp()
return r.request(options.url, {
method: method,
extraData: options.extraData != null ? JSON.stringify(options.extraData) : null
}).then( (response: http.HttpResponse) => {
let netResponse = new NetResponse<T>()
let dataType = typeof response.result
if(dataType === 'string'){
console.log('结果为字符串类型')
}
if(response.responseCode == 200){
netResponse.code = 0
netResponse.msg = 'success'
netResponse.result = JSON.parse(response.result as string)
} else {
//出错
netResponse.code = -1
netResponse.msg = 'error'
}
return netResponse
}).catch( reject => {
console.log('结果发生错误')
let netResponse = new NetResponse<T>()
netResponse.code = reject.code
netResponse.msg = reject.message
return netResponse
}).finally( () => {
//网络请求完成后,需要进行销毁
r.destroy()
})
}
}
export default HNet
//用于装饰器传参
export function Get(targetUrl: string) : MethodDecorator {
return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
//替换方法
descriptor.value = () => {
let options = new NetParams()
options.url = targetUrl
return HNet.get(options)
}
}
}
完整代码
代码结构
net/BasePage.ets
net/NetRequest.ets
net/util/HNet.ts
net/viewmodel/WeiBoModel.ts
net/BizNetController.ets
详细代码
@Component
export struct BasePage {
@Prop netLoad: boolean
@BuilderParam aB0: () => {}
build(){
Stack(){
this.aB0()
if (this.netLoad) {
LoadingProgress()
.width(px2vp(150))
.height(px2vp(150))
.color(Color.Blue)
}
}.hitTestBehavior(HitTestMode.None)
}
}
import HNet from './util/HNet'
import NetController from './BizNetController'
import { WeiBo, WeiBoItem } from './viewmodel/WeiBoModel'
import { BasePage } from './BasePage'
@Entry
@Component
struct NetIndex {
@State netLoad: number = 0
@State msg: string = ''
@State weiboColor: Color = Color.Black
@State uniColor: Color = Color.Black
@State huaweiColor: Color = Color.Black
@State weiboIndex: number = 1
@State uniIndex: number = 2
@State huaweiIndex: number = 3
private TEST_Target_URL: string[] = [
'https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188',
'https://unidemo.dcloud.net.cn/api/news',
'https://developer.huawei.com/config/cn/head.json',
]
build() {
Stack(){
BasePage({netLoad: this.netLoad != 0}) {
Column( {space: 20} ){
Row({space: 20}){
Text('WeiBo').fontColor(Color.Black)
Text('UniDemo').fontColor(Color.Black)
Text('HuaWei').fontColor(Color.Black)
}
Row({space: 20}){
Text('WeiBo' + this.weiboIndex).fontColor(this.weiboColor)
Text('UniDemo' + this.uniIndex).fontColor(this.uniColor)
Text('HuaWei' + this.huaweiIndex).fontColor(this.huaweiColor)
}
Button('开始网络请求 - 异步').fontSize(20).onClick( () => {
this.weiboColor = Color.Black
this.uniColor = Color.Black
this.huaweiColor = Color.Black
this.weiboIndex = 1
this.uniIndex = 2
this.huaweiIndex = 3
this.asyncGetData()
})
Button('开始网络请求 - 同步').fontSize(20).onClick( () => {
this.weiboColor = Color.Black
this.uniColor = Color.Black
this.huaweiColor = Color.Black
this.weiboIndex = 1
this.uniIndex = 2
this.huaweiIndex = 3
this.syncGetData()
})
Button('开始网络请求-自定义方法装饰器').fontSize(20).onClick( () => {
this.getWeiBoListByController()
})
Scroll() {
Text(this.msg).width('100%')
}
.scrollable(ScrollDirection.Vertical)
}
.width('100%')
.height('100%')
.padding({top: px2vp(120)})
}
}
}
asyncGetData(){
this.netLoad = 3;
this.TEST_Target_URL.forEach( (value) => {
HNet.get({
url: value,
}).then( (r) => {
this.msg = JSON.stringify(r)
if(value.indexOf('weibo') != -1){
this.weiboColor = Color.Green
this.weiboIndex = 3 - this.netLoad + 1
} else if(value.indexOf('unidemo') != -1){
this.uniColor = Color.Green
this.uniIndex = 3 - this.netLoad + 1
} else if(value.indexOf('huawei') != -1){
this.huaweiColor = Color.Green
this.huaweiIndex = 3 - this.netLoad + 1
}
this.netLoad--
})
})
}
async syncGetData() {
let starTime
let url
this.netLoad = 3;
starTime = new Date().getTime()
url = this.TEST_Target_URL[0]
starTime = new Date().getTime()
if(url.indexOf('weibo') != -1){
console.log('顺序-请求-weibo')
} else if(url.indexOf('unidemo') != -1){
console.log('顺序-请求-unidemo')
} else if(url.indexOf('huawei') != -1){
console.log('顺序-请求-huawei')
}
await HNet.get<WeiBo>({
url: url,
}).then( (r) => {
this.msg = ''
if(r.code == 0 && r.result){
r.result.data.statuses.forEach((value: WeiBoItem) => {
this.msg = this.msg.concat(value.created_at + ' ' + value.id + '\n')
})
} else {
this.msg = r.code + ' ' + r.msg
}
if(url.indexOf('weibo') != -1){
this.weiboColor = Color.Green
this.weiboIndex = 3 - this.netLoad + 1
console.log('顺序-返回-weibo-' + (new Date().getTime() - starTime))
} else if(url.indexOf('unidemo') != -1){
this.uniColor = Color.Green
this.uniIndex = 3 - this.netLoad + 1
console.log('顺序-返回-unidemo-' + (new Date().getTime() - starTime))
} else if(url.indexOf('huawei') != -1){
this.huaweiColor = Color.Green
this.huaweiIndex = 3 - this.netLoad + 1
console.log('顺序-返回-huawei-' + (new Date().getTime() - starTime))
}
this.netLoad--
})
starTime = new Date().getTime()
url = this.TEST_Target_URL[1]
starTime = new Date().getTime()
if(url.indexOf('weibo') != -1){
console.log('顺序-请求-weibo')
} else if(url.indexOf('unidemo') != -1){
console.log('顺序-请求-unidemo')
} else if(url.indexOf('huawei') != -1){
console.log('顺序-请求-huawei')
}
await HNet.get({
url: url,
}).then( (r) => {
this.msg = JSON.stringify(r)
if(url.indexOf('weibo') != -1){
this.weiboColor = Color.Green
this.weiboIndex = 3 - this.netLoad + 1
console.log('顺序-返回-weibo-' + (new Date().getTime() - starTime))
} else if(url.indexOf('unidemo') != -1){
this.uniColor = Color.Green
this.uniIndex = 3 - this.netLoad + 1
console.log('顺序-返回-unidemo-' + (new Date().getTime() - starTime))
} else if(url.indexOf('huawei') != -1){
this.huaweiColor = Color.Green
this.huaweiIndex = 3 - this.netLoad + 1
console.log('顺序-返回-huawei-' + (new Date().getTime() - starTime))
}
this.netLoad--
})
starTime = new Date().getTime()
url = this.TEST_Target_URL[2]
starTime = new Date().getTime()
if(url.indexOf('weibo') != -1){
console.log('顺序-请求-weibo')
} else if(url.indexOf('unidemo') != -1){
console.log('顺序-请求-unidemo')
} else if(url.indexOf('huawei') != -1){
console.log('顺序-请求-huawei')
}
await HNet.get({
url: url,
}).then( (r) => {
this.msg = JSON.stringify(r)
if(url.indexOf('weibo') != -1){
this.weiboColor = Color.Green
this.weiboIndex = 3 - this.netLoad + 1
console.log('顺序-返回-weibo-' + (new Date().getTime() - starTime))
} else if(url.indexOf('unidemo') != -1){
this.uniColor = Color.Green
this.uniIndex = 3 - this.netLoad + 1
console.log('顺序-返回-unidemo-' + (new Date().getTime() - starTime))
} else if(url.indexOf('huawei') != -1){
this.huaweiColor = Color.Green
this.huaweiIndex = 3 - this.netLoad + 1
console.log('顺序-返回-huawei-' + (new Date().getTime() - starTime))
}
this.netLoad--
})
}
getHuaWeiSomeDataByNet(){
this.netLoad = 1
let starTime = new Date().getTime()
console.log('顺序-huawei-请求' + starTime)
HNet.get({
url: 'https://developer.huawei.com/config/cn/head.json',
}).then( (r) => {
this.msg = JSON.stringify(r, null, '\t')
this.netLoad--
console.log('顺序-huawei-' + (new Date().getTime() - starTime))
})
}
getWeiBoListByHNet(){
this.netLoad = 1
let starTime = new Date().getTime()
console.log('顺序-weibo-请求' + starTime)
HNet.get<WeiBo>({
url: 'https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188',
}).then( (r) => {
this.msg = ''
if(r.code == 0 && r.result){
r.result.data.statuses.forEach((value: WeiBoItem) => {
this.msg = this.msg.concat(value.created_at + ' ' + value.id + '\n')
})
} else {
this.msg = r.code + ' ' + r.msg
}
console.log('顺序-weibo-' + (new Date().getTime() - starTime))
this.netLoad--
})
}
getWeiBoListByController(){
this.netLoad = 1
NetController.getWeiBo<WeiBo>().then( r => {
this.msg = ''
if(r.code == 0 && r.result){
r.result.data.statuses.forEach((value: WeiBoItem) => {
this.msg = this.msg.concat(value.created_at + ' ' + value.id + '\n' + value.source + '\n')
})
} else {
this.msg = r.code + ' ' + r.msg
}
this.netLoad--
})
}
}
import { Get, NetResponse } from './util/HNet'
export default class BizNetController {
@Get('https://m.weibo.cn/api/feed/trendtop?containerid=102803_ctg1_4188_-_ctg1_4188')
static getWeiBo<WeiBo>(): Promise<NetResponse<WeiBo>>{ return }
}
import http from '@ohos.net.http';
class NetParams{
url: string
extraData?: JSON
}
export class NetResponse<T> {
result: T
code: number
msg: string
}
class HNet {
static post<T>(options: NetParams): Promise<NetResponse<T>>{
return this.request(options, http.RequestMethod.POST)
}
static get<T>(options: NetParams): Promise<NetResponse<T>>{
return this.request(options, http.RequestMethod.GET)
}
private static request<T>(options: NetParams, method: http.RequestMethod): Promise<NetResponse<T>>{
let r = http.createHttp()
return r.request(options.url, {
method: method,
extraData: options.extraData != null ? JSON.stringify(options.extraData) : null
}).then( (response: http.HttpResponse) => {
let netResponse = new NetResponse<T>()
let dataType = typeof response.result
if(dataType === 'string'){
console.log('结果为字符串类型')
}
if(response.responseCode == 200){
netResponse.code = 0
netResponse.msg = 'success'
netResponse.result = JSON.parse(response.result as string)
} else {
//出错
netResponse.code = -1
netResponse.msg = 'error'
}
return netResponse
}).catch( reject => {
console.log('结果发生错误')
let netResponse = new NetResponse<T>()
netResponse.code = reject.code
netResponse.msg = reject.message
return netResponse
}).finally( () => {
r.destroy()
})
}
}
export default HNet
export function Get(targetUrl: string) : MethodDecorator {
return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => {
//替换方法
descriptor.value = () => {
let options = new NetParams()
options.url = targetUrl
return HNet.get(options)
}
}
}
export class WeiBo{
ok: number
http_code: number
data: WeiBoDataObj
}
export class WeiBoDataObj{
total_number: number
interval: number
remind_text: string
page: number
statuses: Array<WeiBoItem>
}
export class WeiBoItem{
created_at: string
id: string
source: string
textLength: number
}
- 程序开发学习排行
-
- 1鸿蒙HarmonyOS:Web组件网页白屏检测
- 2HTTPS协议是安全传输,为啥还要再加密?
- 3HarmonyOS鸿蒙应用开发——数据持久化Preferences
- 4记解决MaterialButton背景颜色与设置值不同
- 5鸿蒙HarmonyOS实战-ArkUI组件(RelativeContainer)
- 6鸿蒙HarmonyOS实战-ArkUI组件(Stack)
- 7[Android][NDK][Cmake]一文搞懂Android项目中的Cmake
- 8Android广播如何解决Sending non-protected broadcast问题
- 9鸿蒙HarmonyOS实战-ArkUI组件(mediaquery)
- 最近发表
-
- WooCommerce最好的WordPress常用插件下载博客插件模块的相关产品
- 羊驼机器人最好的WordPress常用插件下载博客插件模块
- IP信息记录器最好的WordPress常用插件下载博客插件模块
- Linkly for WooCommerce最好的WordPress常用插件下载博客插件模块
- 元素聚合器Forms最好的WordPress常用插件下载博客插件模块
- Promaker Chat 最好的WordPress通用插件下载 博客插件模块
- 自动更新发布日期最好的WordPress常用插件下载博客插件模块
- WordPress官方最好的获取回复WordPress常用插件下载博客插件模块
- Img to rss最好的wordpress常用插件下载博客插件模块
- WPMozo为Elementor最好的WordPress常用插件下载博客插件模块添加精简版