HarmonyOS笔记3:从网络数据接口API获取数据

面向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,代码如下所示:

typescript 复制代码
{
  "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接口开发步骤

  1. 从@kit.NetworkKit中导入http命名空间。 调用createHttp()方法,创建一个HttpRequest对象。
  2. 调用该对象的on()方法,订阅http响应头事件,此接口会比request请求先返回。可以根据业务需要订阅此消息。
  3. 调用该对象的request()方法,传入http请求的url地址和可选参数,发起网络请求。 按照实际业务需要,解析返回结果。
  4. 调用该对象的off()方法,取消订阅http响应头事件。
  5. 当该请求使用完毕时,调用destroy()方法主动销毁。

下列的代码实现了对上述的api的访问,具体内容如下:

修改界面的Index.ets

typescript 复制代码
//导入包
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:

typescript 复制代码
interface ReceivedData{
  message,
  status
}

然后将JSON字符串解析成ReceivedData对象,代码段如下:

typescript 复制代码
//将获取的数据转换成JSON字符串
let result = JSON.stringify(response.result)
console.info(`响应的数据结果是:${result}`)
//解析JSON字符串转换成数据对象
let data:ReceivedData = JSON.parse(result)

通过这样的方式获取了特定的对象。

5.使用解析后的数据

修改Index.ets代码,修改UI界面,使得点击按钮不断刷新界面,完整的Index.ets代码如下:

typescript 复制代码
//导入包
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

相关推荐
网络安全-杰克16 分钟前
网络安全概论
网络·web安全·php
怀澈12220 分钟前
高性能服务器模型之Reactor(单线程版本)
linux·服务器·网络·c++
耗同学一米八1 小时前
2024 年河北省职业院校技能大赛网络建设与运维赛项样题二
运维·网络·mariadb
美式小田1 小时前
单片机学习笔记 9. 8×8LED点阵屏
笔记·单片机·嵌入式硬件·学习
skywalk81631 小时前
树莓派2 安装raspberry os 并修改成固定ip
linux·服务器·网络·debian·树莓派·raspberry
猫爪笔记1 小时前
前端:HTML (学习笔记)【2】
前端·笔记·学习·html
_不会dp不改名_1 小时前
HCIA笔记3--TCP-UDP-交换机工作原理
笔记·tcp/ip·udp
C++忠实粉丝1 小时前
计算机网络socket编程(3)_UDP网络编程实现简单聊天室
linux·网络·c++·网络协议·计算机网络·udp
黑客Ela1 小时前
网络安全中常用浏览器插件、拓展
网络·安全·web安全·网络安全·php
qdprobot2 小时前
ESP32桌面天气摆件加文心一言AI大模型对话Mixly图形化编程STEAM创客教育
网络·人工智能·百度·文心一言·arduino