基本概念
UIAbility组件:一种包含UI的应用组件,主要用于和用户交互。
ExtensionAbility组建:基于特定场景,如服务卡片、输入法等提供的应用组件,每一个具体场景对应一个ExtensionAbilityType,开发者只能使用系统已定义的类型。
HAP:应用安装的基本单位
AbilityStage:Module级别的组件容器,与HAP是一一对应的关系。
UIAbility组件概述
UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个UIAbility组件。例如,在支付应用中,可以将入口功能和收付款功能分别配置为独立的UIAbility。
每一个UIAbility组件实例都会在最近任务列表中显示一个对应的任务。
-
如果开发者希望在任务视图中看到一个任务,建议使用“一个UIAbility+多个页面”的方式,可以避免不必要的资源加载。
-
如果开发者希望在任务视图中看到多个任务,或者需要同时开启多个窗口,建议使用多个UIAbility实现不同的功能。
例如,即时通讯类应用中的消息列表与音视频通话采用不同的UIAbility进行开发,既可以方便地切换任务窗口,又可以实现应用的两个任务窗口在一个屏幕上分屏显示。
UIAbility组件的基本用法
指定UIAbility的启动页面以及获取UIAbility的上下文UIAbilityContext。
1. 指定UIAbility的启动页面
应用中的UIAbility在启动过程中,需要指定启动页面,否则应用启动后会因为没有默认加载页面而导致白屏。可以在UIAbility的onWindowStageCreate()生命周期回调中,通过WindowStage对象的loadContent()方法设置启动页面。
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
windowStage.loadContent('pages/Index', (err, data) => {
// ...
});
}
// ...
}
2. 获取UIAbility的上下文信息
UIAbility类拥有自身的上下文信息,该信息为UIAbilityContext类的实例,UIAbilityContext类拥有abilityInfo、currentHapModuleInfo等属性。通过UIAbilityContext可以获取UIAbility的相关配置信息,如包代码路径、Bundle名称、Ability名称和应用程序需要的环境状态等属性信息。
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 获取UIAbility实例的上下文
let context = this.context;
// ...
}
}
在页面中获取Context信息:1.导入common模块 2. 定义context变量
import { common, Want } from '@kit.AbilityKit';
@Entry
@Component
struct Page_EventHub {
private context = getContext(this) as common.UIAbilityContext;
startAbilityTest(): void {
let want: Want = {
// Want参数信息
};
this.context.startAbility(want);
}
// 页面展示
build() {
// ...
}
}
可以调用context方法来终结当前UIAbility实例。
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Page_UIAbilityComponentsBasicUsage {
// 页面展示
build() {
Column() {
//...
Button('FuncAbilityB')
.onClick(() => {
let context = getContext(this) as common.UIAbilityContext;
try {
context.terminateSelf((err: BusinessError) => {
if (err.code) {
// 处理业务逻辑错误
console.error(`terminateSelf failed, code is ${err.code}, message is ${err.message}`);
return;
}
// 执行正常业务
console.info('terminateSelf succeed');
});
} catch (err) {
// 捕获同步的参数错误
let code = (err as BusinessError).code;
let message = (err as BusinessError).message;
console.error(`terminateSelf failed, code is ${code}, message is ${message}`);
}
})
}
}
}
什么是Context?
Context模块继承自BaseContext,提供了ability或application的上下文的能力,包括访问特定应用程序的资源等。它就像是 UIAbility
与其他系统资源以及应用内部信息沟通的桥梁。
其提供了应用的一些基础信息,例如resourceManager(资源管理)、applicationInfo(当前应用信息)、dir(应用文件路径)、area(文件分区)等,以及应用的一些基本方法,例如createBundleContext()、getApplicationContext()等。
Context的典型使用场景
获取应用文件路径https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/application-context-stage-V5#获取应用文件路径
UIAbility组件与UI的数据同步
开发时,多个页面或多个UIAbility中,有一些需要共享的UI数据,有多种方式可以实现。
使用AppStorage/LocalStorage进行数据同步
ArkUI提供了AppStorage和LocalStorage两种应用级别的状态管理方案,可用于实现应用级别和UIAbility级别的数据同步。使用这些方案可以方便地管理应用状态,提高应用性能和用户体验。
其中,AppStorage是一个全局的状态管理器,适用于多个UIAbility共享同一状态数据的情况;
而LocalStorage则是一个局部的状态管理器,适用于单个UIAbility内部使用的状态数据。
LocalStorage:页面级UI状态存储
LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。
1. 创建 LocalStorage 实例
在页面入口或组件中创建 LocalStorage 实例,并初始化属性。
let storage: LocalStorage = new LocalStorage();
storage.setOrCreate('PropA', 47);
2. 使用 @LocalStorageLink 装饰器绑定属性
在 UI 组件中使用 @LocalStorageLink
装饰器,与 LocalStorage 中的属性建立双向数据同步。
@Component
struct Index {
@LocalStorageLink('PropA') localStorageLink: number = 1;
build() {
Column() {
Text(`From LocalStorage ${this.localStorageLink}`)
.onClick(() => {
this.localStorageLink += 1;
});
}
}
}
3. 页面内同步
LocalStorage 的页面级特性使得同一页面内的组件可以共享状态。当一个组件修改状态时,页面内的其他组件会自动同步更新。
@Component
struct Child {
@LocalStorageLink('PropA') childLink: number = 1;
build() {
Column() {
Text(`From LocalStorage in Child ${this.childLink}`);
}
}
}
AppStorage:应用全局的UI状态存储
AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。
1. 设置 AppStorage 属性
AppStorage 是单例,可以通过静态方法 AppStorage.setOrCreate(key, value)
设置或创建属性。
AppStorage.setOrCreate('PropA', 47);
2. 使用 @StorageLink 装饰器绑定属性
在 UI 组件中使用 @StorageLink
装饰器,与 AppStorage 中的属性建立双向数据同步。
@Component
struct Index {
@StorageLink('PropA') storageLink: number = 1;
build() {
Column() {
Text(`From AppStorage ${this.storageLink}`)
.onClick(() => {
this.storageLink += 1;
});
}
}
}
3. 多页面同步
AppStorage 的全局特性使得不同页面可以共享状态。当一个页面修改状态时,其他页面会自动同步更新。
@Component
struct OtherPage {
@StorageLink('PropA') storageLink: number = 1;
build() {
Column() {
Text(`From AppStorage in OtherPage ${this.storageLink}`);
}
}
}
-
AppStorage:适用于应用全局状态共享,如用户登录状态、主题模式等,这些状态需要在多个页面或 Ability 之间共享。
-
LocalStorage:适用于页面内部状态共享,如表单数据、页面切换状态等,这些状态不需要跨页面或 Ability 。
使用Stage模型进行项目构建
DevEco Studio创建出的默认工程仅包含一个的entry类型的模块,如果直接平级目录进行模块管理,工程逻辑结构较混乱且模块间的依赖关系不够清晰,不利于多人开发和维护。
开发过程推荐使用三层架构
三层工程结构如下:
-
commons(公共能力层):用于存放公共基础能力集合(如工具库、公共配置等)。commons层可编译成一个或多个HAR包或HSP包,只可以被products和features依赖,不可以反向依赖。
-
features(基础特性层):用于存放基础特性集合(如应用中相对独立的各个功能的UI及业务逻辑实现等)。各个feature高内聚、低耦合、可定制,供产品灵活部署。不需要单独部署的feature通常编译为HAR包或HSP包,供products或其它feature使用。需要单独部署的feature通常编译为Feature类型的HAP包,和products下Entry类型的HAP包进行组合部署。features层可以横向调用及依赖common层,同时可以被products层不同设备形态的HAP所依赖,但是不能反向依赖products层。
-
products(产品定制层):用于针对不同设备形态进行功能和特性集成。products层各个子目录各自编译为一个Entry类型的HAP包,作为应用主入口。products层不可以横向调用。
三层架构配置方法华为终端Codelabs提供技术专家指导、教程和动手编码体验,在这里你能了解到华为各项最新的尖端技术,并与华为技术专家&全国各地的coder分享知识与见解,一起探索代码的独特魅力。https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/tutorials_Next-BasicArchitectureDesignPart2
HAP
HAP(Harmony Ability Package)是应用安装和运行的基本单元。HAP包是由代码、资源、第三方库、配置文件等打包生成的模块包,其主要分为两种类型:entry和feature。
HAPhttps://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V14/hap-package-V14
HAR
HAR(Harmony Archive)是静态共享包,可以包含代码、C++库、资源和配置文件。通过HAR可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。HAR不同于HAP,不能独立安装运行在设备上,只能作为应用模块的依赖项被引用。
开发静态共享包https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-har-V5
HSP
DevEco Studio支持开发动态共享包HSP(Harmony Shared Package)。在应用/元服务开发过程中部分功能按需动态下载,或开发元服务场景时需要分包加载,可使用HSP实现相应功能。当有多个安装包需要资源共享时,也可利用HSP减少公共资源和代码重复打包。
开发动态共享包https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-hsp-V5
导出ArkUI组件
创建好HSP和HAR包后,需要在包内导出相关组件
声明组件
// library/src/main/ets/components/mainpage/MainPage.ets
@Component
export struct MainPage {
@State message: string = 'HAR MainPage';
build() {
Column() {
Row() {
Text(this.message)
.fontSize(32)
.fontWeight(FontWeight.Bold)
}
.margin({ top: '32px' })
.height(56)
.width('624px')
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center, alignContent: FlexAlign.Center }) {
Column() {
Image($r('app.media.pic_empty')).width('33%')
Text($r('app.string.empty'))
.fontSize(14)
.fontColor($r('app.color.text_color'))
}
}.width('100%')
.height('90%')
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.page_background'))
}
}
HAR对外暴露的接口,在Index.ets导出文件中声明如下所示:
// library/Index.ets
export { MainPage } from './src/main/ets/components/mainpage/MainPage';
随后MainPage组件可以被其他Module引用。
引用共享包(HAR、HSP)
通过如下两种方式设置三方包依赖信息:
- 方式一:在Terminal窗口中,切换到需要引入三方包的模块,如entry模块,执行如下命令安装三方包,DevEco Studio会自动在该模块的oh-package.json5中自动添加三方包依赖。
cd path/to/your/project/entry
ohpm install @ohos/lottie
- 方式二:在需要引入三方包的模块的oh-package.json5中设置三方包依赖,配置示例如下:
"dependencies": {
"@ohos/lottie": "^2.0.0"
}
- 依赖设置完成后,需要执行ohpm install命令安装依赖包,依赖包会安装到该模块的oh_modules目录下。
ohpm install
引用本地模块源码(该本地模块必须与宿主模块归属于同一个工程),如entry模块需要依赖foo模块的源码,有如下两种方式:
- 方式一:在Terminal窗口中,切换到需要引入本地模块源码的模块,即entry模块下,执行如下命令进行安装,并会在该模块下的oh-package.json5中自动添加依赖。
cd path/to/your/project/entry
ohpm install path/to/foo
- 方式二:在需要引入本地模块源码的模块的oh-package.json5中设置源码依赖项,即entry模块的oh-package.json5中,添加如下配置:
"dependencies": {
"foo": "file:path/to/foo" // 此处也可以是以当前oh-package.json5所在目录为起点的相对路径
}
- 依赖设置完成后,需要执行ohpm install命令安装依赖包,模块foo的源码会安装在entry模块的oh_modules目录下。
ohpm install