当前位置: 首页 > news >正文

HarmonyOS

UIAbility

UIAbility 组件是一种包含UI的应用组件,主要用于和用户交互
设计理念:原生支持应用组件的跨端迁移和多端协同、支持多设备和多窗口的形态
UIAbility组件是系统调度的基本单位,为应用提供绘制界面的窗口。

在这里插入图片描述

/**
为使应用能够正常使用UIAbility,
需要在module.json5配置文件的abilities标签中声明UIAbility
的名称、入口、标签等相关信息。
*/
{"module": {// ..."abilities": [{"name": "EntryAbility", // UIAbility组件的名称"srcEntry": "./ets/entryability/EntryAbility.ets", // UIAbility组件的代码路径"description": "$string:EntryAbility_desc", // UIAbility组件的描述信息"icon": "$media:icon", // UIAbility组件的图标"label": "$string:EntryAbility_label", // UIAbility组件的标签"startWindowIcon": "$media:icon", // UIAbility组件启动页面图标资源文件的索引"startWindowBackground": "$color:start_window_background", // UIAbility组件启动页面背景颜色资源文件的索引// ...}]}
}

生命周期

生命周期

Create状态

Create状态为在应用加载过程中,UIAbility实例创建完成时触发,系统会调用onCreate()回调。可以在该回调中进行页面初始化操作,例如变量定义资源加载等,用于后续的UI展示。

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 页面初始化// Want是对象间信息传递的载体,可以用于应用组件间的信息传递}// ...
}

WindowStageCreate和WindowStageDestroy状态

UIAbility实例创建完成之后,在进入Foreground之前,系统会创建一个WindowStage。WindowStage创建完成后会进入onWindowStageCreate()回调,可以在该回调中设置UI加载、设置WindowStage的事件订阅。
在UIAbility实例销毁之前,则会先进入onWindowStageDestroy()回调,可以在该回调中释放UI资源。

在这里插入图片描述

import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';const TAG: string = '[EntryAbility]';
const DOMAIN_NUMBER: number = 0xFF00;export default class EntryAbility extends UIAbility {// ...onWindowStageCreate(windowStage: window.WindowStage): void {windowStage.loadContent('pages/Index', (err, data) => {// 应用中的UIAbility在启动过程中,需要指定启动页面,// 否则应用启动后会因为没有默认加载页面而导致白屏。});// 设置WindowStage的事件订阅(// 获焦/失焦、切到前台/切到后台、前台可交互/前台不可交互)try {windowStage.on('windowStageEvent', (data) => {let stageEventType: window.WindowStageEventType = data;switch (stageEventType) {case window.WindowStageEventType.SHOWN: // 切到前台hilog.info(DOMAIN_NUMBER, TAG, `windowStage foreground.`);break;case window.WindowStageEventType.ACTIVE: // 获焦状态hilog.info(DOMAIN_NUMBER, TAG, `windowStage active.`);break;case window.WindowStageEventType.INACTIVE: // 失焦状态hilog.info(DOMAIN_NUMBER, TAG, `windowStage inactive.`);break;case window.WindowStageEventType.HIDDEN: // 切到后台hilog.info(DOMAIN_NUMBER, TAG, `windowStage background.`);break;case window.WindowStageEventType.RESUMED: // 前台可交互状态hilog.info(DOMAIN_NUMBER, TAG, `windowStage resumed.`);break;case window.WindowStageEventType.PAUSED: // 前台不可交互状态hilog.info(DOMAIN_NUMBER, TAG, `windowStage paused.`);break;default:break;}});} catch (exception) {hilog.error(DOMAIN_NUMBER, TAG,`Failed to enable the listener for window stage event changes. Cause: ${JSON.stringify(exception)}`);}hilog.info(DOMAIN_NUMBER, TAG, `%{public}s`, `Ability onWindowStageCreate`);// 设置UI加载windowStage.loadContent('pages/Index', (err, data) => {// ...});}onWindowStageDestroy() {// 释放UI资源}
}

Foreground和Background状态

Foreground和Background状态分别在UIAbility实例切换至前台和切换至后台时触发,对应于onForeground()回调和onBackground()回调。
onForeground()回调,在UIAbility的UI可见之前,如UIAbility切换至前台时触发。可以在onForeground()回调中申请系统需要的资源,或者重新申请在onBackground()中释放的资源。
onBackground()回调,在UIAbility的UI完全不可见之后,如UIAbility切换至后台时候触发。可以在onBackground()回调中释放UI不可见时无用的资源,或者在此回调中执行较为耗时的操作,例如状态保存等。

import { UIAbility } from '@kit.AbilityKit';export default class EntryAbility extends UIAbility {// ...onForeground(): void {// 申请系统需要的资源,或者重新申请在onBackground()中释放的资源}onBackground(): void {// 释放UI不可见时无用的资源,或者在此回调中执行较为耗时的操作// 例如状态保存等}
}

当应用的UIAbility实例已创建,且UIAbility配置为singleton启动模式时,再次调用startAbility()方法启动该UIAbility实例时,只会进入该UIAbility的onNewWant()回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调。应用可以在该回调中更新要加载的资源和数据等,用于后续的UI展示。

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';export default class EntryAbility extends UIAbility {// ...onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam) {// 更新资源、数据}
}

Destroy状态

Destroy状态在UIAbility实例销毁时触发。可以在onDestroy()回调中进行系统资源的释放、数据的保存等操作。

UIAbility组件启动模式

  • singleton(单实例模式)

    每次调用startAbility()方法时,如果应用进程中该类型的UIAbility实例已经存在,则复用系统中的UIAbility实例。系统中只存在唯一一个该UIAbility实例,即在最近任务列表中只存在一个该类型的UIAbility实例(由于启动的还是原来的UIAbility实例,并未重新创建一个新的UIAbility实例,此时只会进入该UIAbility的onNewWant()回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调)。

  • multiton(多实例模式)

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

  • specified(指定实例模式)

    specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。

UIAbility组件与UI的数据同步

  • 使用EventHub进行数据通信:在基类Context中提供了EventHub对象,可以通过发布订阅方式来实现事件的传递。在事件传递前,订阅者需要先进行订阅,当发布者发布事件时,订阅者将接收到事件并进行相应处理。
// UIAbility
import { hilog } from '@kit.PerformanceAnalysisKit';
import { UIAbility, Context, Want, AbilityConstant } from '@kit.AbilityKit';const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[EventAbility]';export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 获取eventHublet eventhub = this.context.eventHub;// 执行订阅操作eventhub.on('event1', this.eventFunc);eventhub.on('event1', (data: string) => {// 触发事件,完成相应的业务操作});hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onCreate');}// ...eventFunc(argOne: Context, argTwo: Context): void {hilog.info(DOMAIN_NUMBER, TAG, '1. ' + `${argOne}, ${argTwo}`);return;}
}// UI
import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';@Entry
@Component
struct Page_EventHub {private context = getContext(this) as common.UIAbilityContext;eventHubFunc(): void {// 不带参数触发自定义“event1”事件this.context.eventHub.emit('event1');// 带1个参数触发自定义“event1”事件this.context.eventHub.emit('event1', 1);// 带2个参数触发自定义“event1”事件this.context.eventHub.emit('event1', 2, 'test');// 开发者可以根据实际的业务场景设计事件传递的参数}build() {Column() {// ...List({ initialIndex: 0 }) {ListItem() {Row() {// ...}.onClick(() => {this.eventHubFunc();promptAction.showToast({message: 'EventHubFuncA'});})}// ...ListItem() {Row() {// ...}.onClick(() => {this.context.eventHub.off('event1');promptAction.showToast({message: 'EventHubFuncB'});})}// ...}// ...}// ...}
}
  • 使用AppStorage/LocalStorage进行数据同步:ArkUI提供了AppStorage和LocalStorage两种应用级别的状态管理方案,可用于实现应用级别和UIAbility级别的数据同步。

AbilityStage组件容器

AbilityStage是一个Module级别的组件容器,应用的HAP在首次加载时会创建一个AbilityStage实例,可以对该Module进行初始化等操作。
AbilityStage与Module一一对应,即一个Module拥有一个AbilityStage。

DevEco Studio默认工程中未自动生成AbilityStage,如需要使用AbilityStage的能力,可以手动新建一个AbilityStage文件,具体步骤如下。

  1. 在工程Module对应的ets目录下,右键选择“New > Directory”,新建一个目录并命名为myabilitystage。

  2. 在myabilitystage目录,右键选择“New > ArkTS File”,新建一个文件并命名为MyAbilityStage.ets。

  3. 打开MyAbilityStage.ets文件,导入AbilityStage的依赖包,自定义类继承AbilityStage并加上需要的生命周期回调,示例中增加了一个onCreate()生命周期回调。

import { AbilityStage, Want } from '@kit.AbilityKit';export default class MyAbilityStage extends AbilityStage {onCreate(): void {// 应用HAP首次加载时触发,可以在此执行该Module的初始化操作(例如资源预加载、线程创建等)。}onAcceptWant(): void {// UIAbility指定实例模式(specified)启动时候触发的事件回调}onAcceptWant(want: Want): string {// 当系统调整内存时触发的事件// 仅specified模式下触发return 'MyAbilityStage';}
}
// 在module.json5配置文件中,
// 通过配置 srcEntry 参数来指定模块对应的代码路径,以作为HAP加载的入口。
{"module": {"name": "entry","type": "entry","srcEntry": "./ets/myabilitystage/MyAbilityStage.ets",// ...}
}

UIAbility组件间的交互

假设应用中有两个UIAbility:EntryAbility和FuncAbility(可以在同一个Module中,也可以在不同的Module中),需要从EntryAbility的页面中启动FuncAbility。

// EntryAbility
import { common, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';const TAG: string = '[Page_UIAbilityComponentsInteractive]';
const DOMAIN_NUMBER: number = 0xFF00;@Entry
@Component
struct Page_UIAbilityComponentsInteractive {private context = getContext(this) as common.UIAbilityContext;build() {Column() {//...List({ initialIndex: 0 }) {ListItem() {Row() {//...}.onClick(() => {// context为Ability对象的成员,在非Ability对象内部调用需要// 将Context对象传递过去let wantInfo: Want = {deviceId: '', // deviceId为空表示本设备bundleName: 'com.samples.stagemodelabilitydevelop',moduleName: 'entry', // moduleName非必选abilityName: 'FuncAbilityA',parameters: {// 自定义信息info: '来自EntryAbility Page_UIAbilityComponentsInteractive页面'},};// context为调用方UIAbility的UIAbilityContextthis.context.startAbility(wantInfo).then(() => {hilog.info(DOMAIN_NUMBER, TAG, 'startAbility success.');}).catch((error: BusinessError) => {hilog.error(DOMAIN_NUMBER, TAG, 'startAbility failed.');});})}//...}//...}//...}
}
// FuncAbility  UIAbility 
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';export default class FuncAbilityA extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 可以通过获取传递过来的want参数的parameters来获取拉起方UIAbility的PID、Bundle Name等信息。// 接收调用方UIAbility传过来的参数let funcAbilityWant = want;let info = funcAbilityWant?.parameters?.info;}//...
}// FuncAbility UI
// 在FuncAbility业务完成之后,如需要停止当前UIAbility实例,
// 在FuncAbility中通过调用terminateSelf()方法实现。import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';const TAG: string = '[Page_FromStageModel]';
const DOMAIN_NUMBER: number = 0xFF00;@Entry
@Component
struct Page_FromStageModel {build() {Column() {//...Button('FuncAbilityB').onClick(() => {// UIAbilityContextlet context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // context为需要停止的UIAbility实例的AbilityContextcontext.terminateSelf((err) => {if (err.code) {hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self. Code is ${err.code}, message is ${err.message}`);return;}});})}//...}
}

官方文档

ArkUI

长列表优化

  1. 懒加载(缓存列表项 cachedCount)
@Entry
@Component
struct MyComponent {private data: MyDataSource = new MyDataSource();aboutToAppear() {for (let i = 0; i <= 20; i++) {this.data.pushData(`Hello ${i}`)}}build() {List({ space: 3 }) {LazyForEach(this.data, (item: string) => {ListItem() {Row() {Text(item).fontSize(50).onAppear(() => {console.info("appear:" + item)})}.margin({ left: 10, right: 10 })}}, (item: string) => item)}.cachedCount(5)}
}

API文档

  1. @Reusable装饰器:组件复用
class MyDataSource implements IDataSource {private dataArray: string[] = [];private listener: DataChangeListener | undefined;public totalCount(): number {return this.dataArray.length;}public getData(index: number): string {return this.dataArray[index];}public pushData(data: string): void {this.dataArray.push(data);}public reloadListener(): void {this.listener?.onDataReloaded();}public registerDataChangeListener(listener: DataChangeListener): void {this.listener = listener;}public unregisterDataChangeListener(listener: DataChangeListener): void {this.listener = undefined;}
}@Entry
@Component
struct ReuseDemo {private data: MyDataSource = new MyDataSource();// ...build() {Column() {List() {LazyForEach(this.data, (item: string) => {ListItem() {CardView({ item: item })}}, (item: string) => item)}}}
}// 复用组件
// 自定义组件被@Reusable装饰器修饰,即表示其具备组件复用的能力;
@Reusable
@Component
export struct CardView {@State item: string = '';// 当一个可复用的自定义组件从复用缓存中重新加入到节点树时,// 触发aboutToReuse生命周期回调,并将组件的构造参数传递给aboutToReuse;aboutToReuse(params: Record<string, Object>): void {this.item = params.item as string;}build() {Column() {Text(this.item).fontSize(30)}.borderWidth(1).height(100)}
}

API文档

  1. 布局优化

http://www.mrgr.cn/news/78850.html

相关文章:

  • 【PPTist】批注、选择窗格
  • 行为分析:LSTM、3D CNN、SlowFast Networks。这三者的优缺点
  • Tableau数据可视化与仪表盘搭建-可视化原则及BI仪表盘搭建
  • 无线配置实验
  • PHP7和PHP8的最佳实践
  • 公共数据授权运营机制建设(六大机制、存在问题、发展路径)
  • winform跨线程更新界面
  • Kafka常用的一些命令
  • QT去除窗口边框(无边框)
  • Java中 HttpURLConnection 和 HttpClient 详解(初学者友好)
  • oracle中删除指定前缀的表
  • Web API基本认知
  • 胖AP和瘦AP的区别
  • C#基础教程
  • 理解字母形状,从而获得含义
  • 【Linux】常用命令二
  • 【实验13】使用预训练ResNet18进行CIFAR10分类
  • Docker基础使用
  • 【MySQL — 数据库基础】MySQL的安装与配置 & 数据库简单介绍
  • LearnOpenGL学习(光照 -- 颜色,基础光照,材质,光照贴图)
  • 数据结构之三:栈和队列
  • Web登录页面设计
  • 用go语言写一个小服务
  • 手机卡限速丨中国移动5G变3G,网速500kb
  • 单链表---移除链表元素
  • LearnOpenGL学习(光照 -- 颜色,基础光照,材质)