鸿蒙应用开发入门学习

179 阅读10分钟

HarmonyOS简介

华为开发的全场景分布式智慧操作系统。

五大应用场景:智能家居、智慧办公、智慧出行、健康运动、影音娱乐。

目前最新版本HarmonyOS NEXT预览版本,api11, 需要向华为申请权限。此分享基于api9。

搭建开发环境

需要安装DevEco Studio,参考华为官方说明

ArkTS

ArkTS = TypeScript + 声明式UI

为什么使用TypeScript

与Android和iOS区分开来,Java/Kotlin、Swift是不宜使用的,TypeScript在前端开发中使用广泛,生态丰富。

为什么使用声明式UI

声明式开发使用起来更加简单方便。相比于React和Vue写UI的方式,简单方便许多,还不需要掌握HTML、CSS。

用过Flutter或者Android Compose都能感受到声明式UI的简单高效。

ArkTS的声明式开发范式

  • 装饰器

用来装饰类、结构体、方法以及变量,赋予其特殊的含义,可以理解为Java中的注解。

@Entry表示这是个入口组件,有这个装饰器才能通过路由跳转;

@Component 表示这是个自定义组件;

@State 表示组件中的状态变量,该装饰器修饰的变量的变化会引起UI的变更;

  • 自定义组件

可复用的 UI 单元,可组合其它组件,如上述被 @Component 装饰的 struct Hello。

  • UI 描述

声明式的方式来描述 UI 的结构,如上述 build() 方法内部的代码块。

  • 内置组件

Harmony OS提供了丰富多样的UI组件,让开发者调用, 如Text、Image、TextInput、Button。developer.huawei.com/consumer/cn…

  • 事件方法

用于添加组件对事件的响应逻辑,统一通过事件方法进行设置,如跟随在Button后面的onClick()。

  • 属性方法

用于组件属性的配置,统一通过属性方法进行设置,如fontSize()、width()、height()、color() 等,可通过链式调用的方式设置多项属性。

了解工程目录文件

工程级目录

  • AppScope中存放应用全局所需要的资源文件。
  • entry是应用的主模块,存放HarmonyOS应用的代码、资源等。
  • oh_modules是工程的依赖包,存放工程依赖的源文件。
  • build-profile.json5是工程级配置信息,包括签名、产品配置等。
  • hvigorfile.ts是工程级编译构建任务脚本,hvigor是基于任务管理机制实现的一款全新的自动化构建工具,主要提供任务注册编排,工程模型管理、配置管理等核心能力。
  • oh-package.json5是工程级依赖配置文件,用于记录引入包的配置信息。

在AppScope,其中有resources文件夹和配置文件app.json5。AppScope>resources>base中包含element和media两个文件夹,

  • 其中element文件夹主要存放公共的字符串、布局文件等资源。
  • media存放全局公共的多媒体资源文件。

模块级目录

entry>src目录中主要包含总的main文件夹,单元测试目录ohosTest,以及模块级的配置文件。

  • main文件夹中,ets文件夹用于存放ets代码,resources文件存放模块内的多媒体及布局文件等,module.json5文件为模块的配置文件。
  • ohosTest是单元测试目录。
  • build-profile.json5是模块级配置信息,包括编译构建配置项。
  • hvigorfile.ts文件是模块级构建脚本。
  • oh-package.json5是模块级依赖配置信息文件。

进入src>main>ets目录中,其分为entryability、pages两个文件夹。

  • entryability存放ability文件,用于当前ability应用逻辑和生命周期管理。
  • pages存放UI界面相关代码文件,初始会生成一个Index页面。

resources目录下存放模块公共的多媒体、字符串及布局文件等资源,分别存放在element、media文件夹中。

app.json5

AppScope>app.json5是应用的全局的配置文件,用于存放应用公共的配置信息。

  • bundleName是包名。
  • vendor是应用程序供应商。
  • versionCode是用于区分应用版本。
  • versionName是版本号。
  • icon对应于应用的显示图标。
  • label是应用名。
module.json5

entry>src>main>module.json5是模块的配置文件,包含当前模块的配置信息。

其中module对应的是模块的配置信息,一个模块对应一个打包后的hap包,hap包全称是HarmonyOS Ability Package,其中包含了ability、第三方库、资源和配置文件。其具体属性及其描述可以参照下表。

属性描述
name该标签标识当前module的名字,module打包成hap后,表示hap的名称,标签值采用字符串表示(最大长度31个字节),该名称在整个应用要唯一。
type表示模块的类型,类型有三种,分别是entry、feature和har。
srcEntry当前模块的入口文件路径。
description当前模块的描述信息。
mainElement该标签标识hap的入口ability名称或者extension名称。只有配置为mainElement的ability或者extension才允许在服务中心露出。
deviceTypes该标签标识hap可以运行在哪类设备上,标签值采用字符串数组的表示。
deliveryWithInstall标识当前Module是否在用户主动安装的时候安装,表示该Module对应的HAP是否跟随应用一起安装。- true:主动安装时安装。- false:主动安装时不安装。
installationFree标识当前Module是否支持免安装特性。- true:表示支持免安装特性,且符合免安装约束。- false:表示不支持免安装特性。
pages对应的是main_pages.json文件,用于配置ability中用到的page信息。
abilities是一个数组,存放当前模块中所有的ability元能力的配置信息,其中可以有多个ability。

对于abilities中每一个ability的属性项,其描述信息如下表。

属性描述
name该标签标识当前ability的逻辑名,该名称在整个应用要唯一,标签值采用字符串表示(最大长度127个字节)。
srcEntryability的入口代码路径。
descriptionability的描述信息。
iconability的图标。该标签标识ability图标,标签值为资源文件的索引。该标签可缺省,缺省值为空。如果ability被配置为MainElement,该标签必须配置。
labelability的标签名。
startWindowIcon启动页面的图标。
startWindowBackground启动页面的背景色。
visibleability是否可以被其他应用程序调用,true表示可以被其它应用调用, false表示不可以被其它应用调用。
skills标识能够接收的意图的action值的集合,取值通常为系统预定义的action值,也允许自定义。
entities标识能够接收Want的Entity值的集合。
actions标识能够接收的Want的Action值的集合,取值通常为系统预定义的action值,也允许自定义。
main_page.json

src/main/resources/base/profile/main_pages.json文件保存的是页面page的路径配置信息,所有需要进行路由跳转的page页面都要在这里进行配置。

UIAbility

应用程序的入口,类似于Android的Application。

一个应用可以有一个UIAbility,也可以有多个UIAbility。每一个UIAbility实例,都对应于一个最近任务列表中的任务。

生命周期

import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';

export default class EntryAbility extends UIAbility {
    
    // 创建
    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
        // 应用初始化
    }
    
    // 进入前台前会创建WindowStage
    onWindowStageCreate(windowStage: window.WindowStage){
        // 指定开屏页面
        windowStage.loadContent('pages/HomePage', (err, data) => {
             
   
        });
    }
    
    // 进入前台
    onForeground(){
        // 申请系统需要的资源
    }

    // 进入后台
    onBackground(){
        // 释放UI页面不可见时无用的资源,或者在此回调中执行较为耗时的操作
        // 例如状态保存等
    }
    // 在实例销毁前调用
    onWindowStageDestroy(){
        // 释放UI页面资源
    }
    
    onDestroy(){
        // 系统资源的释放、数据的保存等
    }
}
启动模式
  • singleton(单实例模式)

singleton启动模式为单实例模式,也是默认情况下的启动模式。

每次调用startAbility()方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例。

  • multiton(多实例模式)

multiton启动模式为多实例模式,每次调用startAbility()方法时,都会在应用进程中创建一个新的该类型UIAbility实例。即在最近任务列表中可以看到有多个该类型的UIAbility实例。这种情况下可以将UIAbility配置为multiton(多实例模式)。

  • specified(指定实例模式)

在startAbility()传入指定key,如果匹配到对应key的实例则利用,否则会创建实例。

在module.json5配置文件中的launchType字段配置启动模式

{
   "module": {
     // ...
     "abilities": [
       {
         "launchType": "singleton", // multiton、specified
         // ...
       }
     ]
  }
}

Page

生命周期

@Entry
@Component
struct Hello {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
  }

  //在执行其build()函数之前执行。
  //允许在aboutToAppear函数中改变状态变量,更改将在后续执行build()函数中生效。
  aboutToAppear(){

  }

  // 页面每次显示时触发一次,
  // 包括路由过程、应用进入前台等场景,仅@Entry装饰的自定义组件生效。
  onPageShow(){

  }

  // aboutToDisappear函数在自定义组件析构销毁之前执行。
  // 不允许在aboutToDisappear函数中改变状态变量
  aboutToDisappear(){

  }
    
  // 页面每次隐藏时触发一次
  // 包括路由过程、应用进入前台等场景,仅@Entry装饰的自定义组件生效。
  onPageHide(){

  }
  // 当用户点击返回按钮时触发,仅@Entry装饰的自定义组件生效。
  onBackPress(){

  }
}
状态管理

ArkUI框架提供了多种管理状态的装饰器来修饰变量,使用这些装饰器修饰的变量即称为状态变量。

当改变状态变量的时候,ArkUI就会自动更新界面中受影响的部分。

装饰器场景
@State组件内的状态管理
@Prop从父组件单向同步状态
@Link与父组件双向同步状态
@Provide和@Consume跨组件层级双向同步状态
页面跳转

导入router模块

import router from '@ohos.router';

方法一

pushUrl

入参:

参数名说明
url要跳转的路由,需要在main_pages.json中指定
params自定义传参
mode可以不传默认,router.RouterMode.Single和router.RouterMode.Standard,默认Standard

在单实例模式下:如果目标页面的url在页面栈中已经存在同url页面,离栈顶最近同url页面会被移动到栈顶,移动后的页面为新建页,原来的页面仍然存在栈中,页面栈的元素数量不变;如果目标页面的url在页面栈中不存在同url页面,按多实例模式跳转,页面栈的元素数量会加1。

router.pushUrl({
  url: 'pages/Second',
  params: {
    src: 'Index页面传来的数据',
  }
}, router.RouterMode.Single)

方法二

replaceUrl

在单实例模式下:如果目标页面的url在页面栈中已经存在同url页面,离栈顶最近同url页面会被移动到栈顶,替换当前页面,并销毁被替换的当前页面,移动后的页面为新建页,页面栈的元素数量会减1;如果目标页面的url在页面栈中不存在同url页面,按多实例模式跳转,页面栈的元素数量不变。

router.replaceUrl({
  url: 'pages/Second',
  params: {
    src: 'Index页面传来的数据',
  }
}, router.RouterMode.Single)

接收参数

通过调用router.getParams()方法获取页面传递过来的自定义参数。

import router from '@ohos.router';

@Entry
@Component
struct Second {
  @State src: string = (router.getParams() as Record<string, string>)['src'];
}

页面返回和参数接收

// 返回
router.back();
// 返回指定页面
router.back({ url: 'pages/Index' });
// 返回指定页面并传参
router.back({
  url: 'pages/Index',
  params: {
    src: 'Second页面传来的数据',
  }
})

接收返回参数:

也是通过router.getParams()接收。

import router from '@ohos.router';
class routerParams {
  src:string
  constructor(str:string) {
    this.src = str
  }
}

@Entry
@Component
struct Index {
  @State src: string = '';
  onPageShow() {
    this.src = (router.getParams() as routerParams).src
  }
}

网络请求

在模块的module.json5中声明网络访问权限

{
    "module" : {
        "requestPermissions":[
           {
             "name": "ohos.permission.INTERNET"
           }
        ]
    }
}

发起网络请求

// 导入http模块
//import http from '@ohos.net.http'; //api9
import { http } from '@kit.NetworkKit'; //api11

let httpRequest = http.createHttp();

// 发起Post请求
let url = "https://EXAMPLE_URL";
let promise = httpRequest.request(
  // 请求url地址
  url,
  {
    // 请求方式
    method: http.RequestMethod.POST,
    // 请求的额外数据。
    extraData: {
      "param1": "value1",
      "param2": "value2",
    },
    // 可选,默认为60s
    connectTimeout: 60000,
    // 可选,默认为60s
    readTimeout: 60000,
    // 开发者根据自身业务需要添加header字段
    header: {
      'Content-Type': 'application/json'
    }
  });
  // 处理请求结果
  promise.then((data) => { 
  if (data.responseCode === http.ResponseCode.OK) {
     console.info('Result:' + data.result);
     console.info('code:' + data.responseCode);
  }
  }).catch((err) => {
     console.info('error:' + JSON.stringify(err));
  });

注:三方库axios