面向HarmonyOS的移动应用一般采用MVVM模式(见参考文献【1】),其中:
M(Model层):模型层,存储数据和相关逻辑的模型。它表示组件或其他相关业务逻辑之间传输的数据。Model是对原始数据的进一步处理。
V(View层):视图层,在ArkUI框架中通常是@Components修饰组件渲染的移动应用界面的UI。
VM(ViewModel层):视图模型层,在ArkUI中,ViewModel是存储在自定义组件的状态变量、LocalStorage和AppStorage中的数据。这些数据为UI提供渲染的内容,同时UI界面也可以通过视图组件修改模型数据。是模型层和视图层的中介。
在创建一个移动应用中,最重要的是获取数据以及对数据的处理。在这篇文章中,主要讨论一下模型层中的数据来源。在HarmonyOS中,获取数据的方式主要有:
1.从网络中获取数据接口API。
2.从华为云数据库获取网络数据库的资源。
3.从移动终端直接获取本地的数据
从这篇文章开始,将分别对以上三种情况简单介绍一下。本篇文章中简单介绍网络中获取并使用数据接口API的数据。
一、数据接口API
API接口的请求方法:常用的HTTP请求方法有GET、POST、PUT、DELETE等,不同的请求方法对应不同的操作。
API的URL:这是你的代码将发送请求的地址。
API的参数:一些API可能需要参数来完成特定的操作,例如,你可能需要提供一个特定的ID来获取某个特定的数据。
API的返回数据:你需要知道API返回的数据的格式(如JSON、XML等)以及数据的含义。
例如:请求“https://dog.ceo/api/breeds/image/random”(关于数据api接口的更详细介绍,见参考文献【2】)返回的JSON数据如下:
请求获取的随机JSON数据如下:
{
“message”:“https://images.dog.ceo/breeds/gaddi-indian/Gaddi.jpg”,
“status”:“success”
}
二、网络访问数据接口API
1.创建一个新的HarmonyOS项目
点击确认创建新的项目。
2.配置网络访问许可
在新项目的entry模块的module.json5配置文件中,新增网络访问许可,同时修改"extensionAbilities"的"exported"属性为true,代码如下所示:
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"requestPermissions": [{
"name": "ohos.permission.INTERNET"
}],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported":true,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
]
}
]
}
}
3.在页面中增加获取API数据的请求
请求网络资源的可以通过request接口来实现
request接口开发步骤
- 从@kit.NetworkKit中导入http命名空间。 调用createHttp()方法,创建一个HttpRequest对象。
- 调用该对象的on()方法,订阅http响应头事件,此接口会比request请求先返回。可以根据业务需要订阅此消息。
- 调用该对象的request()方法,传入http请求的url地址和可选参数,发起网络请求。 按照实际业务需要,解析返回结果。
- 调用该对象的off()方法,取消订阅http响应头事件。
- 当该请求使用完毕时,调用destroy()方法主动销毁。
下列的代码实现了对上述的api的访问,具体内容如下:
修改界面的Index.ets
//导入包
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
@State imageURL: string = ''
aboutToAppear(){
this.doNetwork()
}
build() {
RelativeContainer() {
Text(this.imageURL)
.id('HelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
}
.height('100%')
.width('100%')
}
async doNetwork(){
//设置访问数据api的url链接
let apiUrl = "https://dog.ceo/api/breeds/image/random"
//创建一个Http请求
let httpRequest = http.createHttp()
//订阅http响应头事件
httpRequest.on("headersReceive",(header)=>{
console.info('header: ' + JSON.stringify(header));
})
//请求url
httpRequest.request(apiUrl,{
method:http.RequestMethod.GET,
header:{
'Content-Type':'application/json',
},
usingCache:true,
connectTimeout:6000,//连接时间6s
readTimeout:6000,//读取时间6s
},(err:BusinessError,response:http.HttpResponse)=>{
if(!err){
console.info(`响应的数据结果是:${JSON.stringify(response.result)}`)
}else {
console.error('error:' + JSON.stringify(err));
// 取消订阅HTTP响应头事件
httpRequest.off('headersReceive');
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}
})
}
}
因为界面还未定义,因此运行时,可以在日志窗口中观察到获取到api数据,运行结果如下所示:
但是获取的JSON字符串需要得到具体的属性数据,例如图片的链接地址,因此需要将JSON数据转换成数据对象。
4.解析JSON数据
因为需要解析JSON字符串,定义接口ReceivedData:
interface ReceivedData{
message,
status
}
然后将JSON字符串解析成ReceivedData对象,代码段如下:
//将获取的数据转换成JSON字符串
let result = JSON.stringify(response.result)
console.info(`响应的数据结果是:${result}`)
//解析JSON字符串转换成数据对象
let data:ReceivedData = JSON.parse(result)
通过这样的方式获取了特定的对象。
5.使用解析后的数据
修改Index.ets代码,修改UI界面,使得点击按钮不断刷新界面,完整的Index.ets代码如下:
//导入包
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
@State imageURL: string = ''
aboutToAppear(){
this.doNetwork()
}
build() {
Column() {
if(this.imageURL!=''){
Image(this.imageURL)
.width("100%")
.height(300)
}
Text(this.imageURL)
.id('HelloWorld')
.fontSize(12)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
Button("刷新").onClick(()=>{
this.doNetwork()
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
async doNetwork(){
//设置访问数据api的url链接
let apiUrl = "https://dog.ceo/api/breeds/image/random"
//创建一个Http请求
let httpRequest = http.createHttp()
//订阅http响应头事件
httpRequest.on("headersReceive",(header)=>{
console.info('header: ' + JSON.stringify(header));
})
//请求url
httpRequest.request(apiUrl,{
method:http.RequestMethod.GET,
expectDataType: http.HttpDataType.OBJECT,//指定返回数据的类型
header:{
'Content-Type':'application/json',
},
usingCache:true,
connectTimeout:6000,//连接时间6s
readTimeout:6000,//读取时间6s
},(err:BusinessError,response:http.HttpResponse)=>{
if(!err){
//将获取的数据转换成JSON字符串
let result = JSON.stringify(response.result)
console.info(`响应的数据结果是:${result}`)
//解析JSON字符串转换成数据对象
let data:ReceivedData = JSON.parse(result)
this.imageURL = data.message
console.info(`图片地址:${data.message}-获取状态:${data.status}`)
}else {
console.error('error:' + JSON.stringify(err));
// 取消订阅HTTP响应头事件
httpRequest.off('headersReceive');
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
}
})
}
}
interface ReceivedData{
message,
status
}
最后的运行结果如下图所示:
参考文献
【1】“MVVM模式” HarmonyOS Developer
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-mvvm-V5
【2】“推荐 GitHub 上的一套公开 API 接口,简直不要太全!” 腾讯云开发者社区
http://cloud.tencent.com/developer/article/2082773
【3】“HTTP数据请求” HarmonyOS Developer
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/http-request-V5