立聪堂德州十三局店 发表于 2025-3-30 21:57:28

HarmonyOS

每天学习一点点,连续更新此帖
UIAbility

   UIAbility 组件是一种包含UI的应用组件,重要用于和用户交互
设计理念:原生支持应用组件的跨端迁徙和多端协同、支持多设备和多窗口的形态
UIAbility组件是系统调理的基本单位,为应用提供绘制界面的窗口。
https://i-blog.csdnimg.cn/direct/3cf09591cced431d9c038065f41469a2.png
/**
为使应用能够正常使用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组件启动页面背景颜色资源文件的索引
      // ...
      }
    ]
}
}
生命周期

https://i-blog.csdnimg.cn/direct/3b63d1354b694c07972bab9a977bb950.png
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资源。
https://i-blog.csdnimg.cn/direct/c3272f741f2f44669a884b0eb216edf7.png
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = '';
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 = '';

export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 获取eventHub
    let 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文件,详细步骤如下。

[*] 在工程Module对应的ets目录下,右键选择“New > Directory”,新建一个目录并命名为myabilitystage。
[*] 在myabilitystage目录,右键选择“New > ArkTS File”,新建一个文件并命名为MyAbilityStage.ets。
[*] 打开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 = '';
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的UIAbilityContext
            this.context.startAbility(wantInfo).then(() => {
            hilog.info(DOMAIN_NUMBER, TAG, 'startAbility success.');
            }).catch((error: BusinessError) => {
            hilog.error(DOMAIN_NUMBER, TAG, 'startAbility failed.');
            });
          })
      }
      //...
      }
      //...
    }
    //...
}
}
// FuncAbilityUIAbility
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 = '';
const DOMAIN_NUMBER: number = 0xFF00;

@Entry
@Component
struct Page_FromStageModel {
build() {
    Column() {
      //...
      Button('FuncAbilityB')
      .onClick(() => {
      // UIAbilityContext
          let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
          // context为需要停止的UIAbility实例的AbilityContext
          context.terminateSelf((err) => {
            if (err.code) {
            hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self. Code is ${err.code}, message is ${err.message}`);
            return;
            }
          });
      })
    }
    //...
}
}
官方文档
ArkUI

长列表优化


[*]懒加载(缓存列表项 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文档

[*]@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;
}

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文档

[*]布局优化
动画能力



[*]属性动画: 通过更改组件的属性值实现渐变过渡效果,比方缩放、旋转、平移等。支持的属性包罗width、height、backgroundColor、opacity、scale、rotate、translate等。
[*]显示动画:可以通过用户的直接操纵或应用步伐的特定逻辑来触发,比方按钮点击时的缩放动画、列表项展开时的渐变动画等。HarmonyOS提供了全局animateTo显式动画接口来指定由于闭包代码导致状态变化的插入过渡动效。
[*]转场动画:转场动画可以实现平滑的界面切换效果,比方页面之间的淡入淡出、滑动切换、旋转切换等,增强了界面的连贯性和吸引力
[*]路径动画:指对象沿着指定路径进行移动的动画效果。通过设置路径可以实现视图沿着预定义的路径进行移动,比方曲线运动、圆周运动等,为用户呈现更加生动的交互效果。
[*]粒子动画:通过大量小颗粒的运动来形成团体动画效果。通过对粒子在颜色、透明度、大小、速度、加快度、自旋角度等维度变化做动画,来营造一种氛围感。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: HarmonyOS