Harmony开发笔记8

UIAbility启动模式

什么是UIAbility? UIAbility组件是一种包含UI的应用组件,主要用于和用户交互 。它是HarmonyOS中用于系统调度的基本单元,为应用提供绘制界面的窗口。

其他官方专业数据就不赘述了,简单将就是手机应用里的一个UI窗口。这个类比Android里的Activity,都是UI的应用组件。

官方入口

开发者学堂入口

开发指南入口

基础理论

UIAbility类似Android中的Activity,Activity有4中启动模式,而UIAbility有3中启动模式。HarmonyOS中的UIAbility的启动模式相较于Android更加简化易于理解。

  • singleton(单实例模式)

当你给UIAbility的launchType设置为单实例模式,则无论你启动几次该窗口都将仅有一个窗口,多次启动后仅会进入该UIAbility的onNewWant()回调

  • multiton(多实例模式)

多实例模式也是标准模式(standard),标准模式就旧版称呼。多实例模式就是你启动几次UIAbility就会创建几个新的窗口。

  • specified(指定实例模式)

specified启动模式为指定实例模式,简单说就是自定义启动模式,是多实例还是单实例你自己来实现

实战说明

我们在刚刚新建的项目上右键创建一个新的UIAbility,起名为SingletonAbility,点击完成即可。

idea会自动生成一个名为SingletonAbility的文件,同时将该窗口配置到配置文件中。

同理我们在创建MultitonAbilitySpecifiedUIAbility,同时分别设置相应的launchType

... "abilities": [ ... { "name": "SingletonAbility", "srcEntry": "./ets/singletonability/SingletonAbility.ets", "description": "$string:SingletonAbility_desc", "icon": "$media:layered_image", "label": "$string:SingletonAbility_label", "launchType": "singleton", // 重点这里 "startWindowIcon": "$media:startIcon", "startWindowBackground": "$color:start_window_background" }, { "name": "MultitonAbility", "srcEntry": "./ets/multitonability/MultitonAbility.ets", "description": "$string:MultitonAbility_desc", "icon": "$media:layered_image", "label": "$string:MultitonAbility_label", "launchType": "multiton", // 重点这里 "startWindowIcon": "$media:startIcon", "startWindowBackground": "$color:start_window_background" }, { "name": "SpecifiedAbility", "srcEntry": "./ets/specifiedability/SpecifiedAbility.ets", "description": "$string:SpecifiedAbility_desc", "icon": "$media:layered_image", "launchType": "specified", // 重点这里 "label": "$string:SpecifiedAbility_label", "startWindowIcon": "$media:startIcon", "startWindowBackground": "$color:start_window_background" } ], ...

默认工程指定入口窗口EntryUIAbility使用的是pages/Index.etx的启动页面,我们在这个页面增加几个按钮实现跳转,这样准备工作基本完成。

@Entry @Component struct Index { build() { Column() { Button("打开单实例窗口") .onClick(() => { let context = getContext(this) as common.UIAbilityContext let want: Want = { bundleName: 'com.byrain.example_001', abilityName: 'SingletonAbility' }; context.startAbility(want); }) Button("打开多实例窗口") .onClick(() => { let context = getContext(this) as common.UIAbilityContext let want: Want = { bundleName: 'com.byrain.example_001', abilityName: 'MultitonAbility' }; context.startAbility(want); }) ... // 指定启动模式下面单独说 } .height('100%') .width('100%') } }

几个UIAbility使用的page都是Index.ets,所以界面都是一样的,现在启动应用,

单实例验证

点击打开单实例,会打开新页面,在新页面再次点击打开单实例界面没有反应。我们看日志

02-21 16:07:08.592 13468-13468 A00000/testTag pid-13468 I EntryAbility onCreate 02-21 16:07:08.644 13468-13468 A00000/testTag pid-13468 I EntryAbility onWindowStageCreate 02-21 16:07:08.654 13468-13468 A00000/testTag pid-13468 I EntryAbility onForeground 02-21 16:07:08.710 13468-13468 A00000/testTag pid-13468 I Succeeded in loading the content. 02-21 16:08:08.640 13468-13468 A00000/testTag com.byrai...mple_001 I EntryAbility onBackground 02-21 16:08:08.688 13468-13468 A00000/testTag com.byrai...mple_001 I SingletonAbility onCreate 02-21 16:08:08.717 13468-13468 A00000/testTag com.byrai...mple_001 I SingletonAbility onWindowStageCreate 02-21 16:08:08.730 13468-13468 A00000/testTag com.byrai...mple_001 I SingletonAbility onForeground 02-21 16:08:08.768 13468-13468 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content. 02-21 16:08:10.499 13468-13468 A00000/testTag com.byrai...mple_001 I SingletonAbility onNewWant 02-21 16:08:11.722 13468-13468 A00000/testTag com.byrai...mple_001 I SingletonAbility onNewWant

第一次打开单例窗口后,UIAbility创建新实例,再次单击打开时候则进入onNewWant()回调,当前窗口仅创建一个。

我们通过aa工具查看也确实仅有两个UIAbility

$ aa dump -l User ID #100 current mission lists:{ Mission ID #136 mission name #[#com.byrain.example_001:entry:EntryAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1725 app name [com.byrain.example_001] main name [EntryAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #BACKGROUND start time [98914947] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false } Mission ID #137 mission name #[#com.byrain.example_001:entry:SingletonAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1727 app name [com.byrain.example_001] main name [SingletonAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #FOREGROUND start time [98975152] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false }

多实例验证

我们结束进程,然后从新打开应用,点击打开多实例此时会打开新页面,在新页面点击打开多实例会再次打开个新页面。我们看日志执行

02-21 16:20:32.147 16786-16786 A00000/testTag com.byrai...mple_001 I EntryAbility onCreate 02-21 16:20:32.170 16786-16786 A00000/testTag com.byrai...mple_001 I EntryAbility onWindowStageCreate 02-21 16:20:32.179 16786-16786 A00000/testTag com.byrai...mple_001 I EntryAbility onForeground 02-21 16:20:32.217 16786-16786 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content. 02-21 16:20:34.117 16786-16786 A00000/testTag com.byrai...mple_001 I EntryAbility onBackground 02-21 16:20:34.126 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onCreate 02-21 16:20:34.147 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onWindowStageCreate 02-21 16:20:34.153 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onForeground 02-21 16:20:34.188 16786-16786 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content. 02-21 16:20:36.328 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onBackground 02-21 16:20:36.332 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onCreate 02-21 16:20:36.339 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onWindowStageCreate 02-21 16:20:36.345 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onForeground 02-21 16:20:36.374 16786-16786 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content. 02-21 16:20:38.631 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onCreate 02-21 16:20:38.647 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onWindowStageCreate 02-21 16:20:38.663 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onForeground 02-21 16:20:38.663 16786-16786 A00000/testTag com.byrai...mple_001 I MultitonAbility onBackground 02-21 16:20:38.684 16786-16786 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content.

每次打开都会创建一个新的UIAbility实例,通过aa工具也可以看到有4个UIAbility。

$ aa dump -l User ID #100 current mission lists:{ Mission ID #138 mission name #[#com.byrain.example_001:entry:EntryAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1740 app name [com.byrain.example_001] main name [EntryAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #BACKGROUND start time [99718497] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false } Mission ID #139 mission name #[#com.byrain.example_001:entry:MultitonAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1741 app name [com.byrain.example_001] main name [MultitonAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #BACKGROUND start time [99720633] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false } Mission ID #140 mission name #[#com.byrain.example_001:entry:MultitonAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1742 app name [com.byrain.example_001] main name [MultitonAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #BACKGROUND start time [99722839] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false } Mission ID #141 mission name #[#com.byrain.example_001:entry:MultitonAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1743 app name [com.byrain.example_001] main name [MultitonAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #FOREGROUND start time [99725149] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false }

指定启动模式验证

指定启动模式是自定义页面启动模式,所以不是简单配置后直接调用startAbility,这里需要介绍下AbilityStage

AbilityStage类似Android里的Application,AbilityStage是HarmonyOS中Stage模型的一个核心组件,用于管理应用的生命周期和状态。这里我们主要使用AbilityStageonAcceptWant的生命周期回调,判断指定启动模式的UIAbility是否是单实例主要在这个回调中处理。

我们在Index.etx中增加启动指定启动模式的按钮,在启动时候传入的Want(下一篇介绍)并在其属性parameters中指定参数

Button("打开指定模式为单实例窗口") .onClick(() => { let context = getContext(this) as common.UIAbilityContext let want: Want = { bundleName: 'com.byrain.example_001', abilityName: 'SpecifiedAbility', parameters: { type: 1 } }; context.startAbility(want); }) Button("打开指定模式为多实例窗口") .onClick(() => { let context = getContext(this) as common.UIAbilityContext let num = LocalStorage.getShared().get("type") as number if (num == undefined) { num = 1; } num = num + 1; hilog.info(0x0000, 'testTag', '%{public}s', `启动页面类型值${num}`); let want: Want = { bundleName: 'com.byrain.example_001', abilityName: 'SpecifiedAbility', parameters: { type: num } }; context.startAbility(want); })

然后我们自定义AbilityStage,实现onAcceptWant回调,在这里根据want参数返回字符串

export default class Example_001AbilityStage extends AbilityStage { onAcceptWant(want: Want): string { // 这里的want可以接收startAbility时候传入的want参数 if (want.abilityName === 'SpecifiedAbility' && want.parameters) { // 如果跳转的UIAbility是指定启动模式的UIAbility则根据参数type返回不同的字符串, // 如果每次返回相同的字符串,则代表启动的是单实例UIAbility。这里返回的字符串是UIAbility的唯一标识 if (want.parameters.type) { hilog.info(0x0000, 'testTag', '%{public}s', `接收到的指定启动模式的参数值${want.parameters.type}`); return `SpecifiedAbility${want.parameters.type}` } } return super.onAcceptWant(want) } }

我们重新启动应用,点击打开指定模式为单实例窗口,在打开的新页面再次点击,看日志:

02-21 16:42:27.312 21526-21526 A00000/testTag com.byrai...mple_001 I EntryAbility onCreate 02-21 16:42:27.324 21526-21526 A00000/testTag com.byrai...mple_001 I EntryAbility onWindowStageCreate 02-21 16:42:27.332 21526-21526 A00000/testTag com.byrai...mple_001 I EntryAbility onForeground 02-21 16:42:27.371 21526-21526 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content. 02-21 16:42:29.036 21526-21526 A00000/testTag com.byrai...mple_001 I 接收到的指定启动模式的参数值1 02-21 16:42:29.063 21526-21526 A00000/testTag com.byrai...mple_001 I EntryAbility onBackground 02-21 16:42:29.071 21526-21526 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onCreate 02-21 16:42:29.076 21526-21526 A00000/testTag com.byrai...mple_001 I specifiedability onWindowStageCreate 02-21 16:42:29.079 21526-21526 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onForeground 02-21 16:42:29.098 21526-21526 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content. 02-21 16:42:30.027 21526-21526 A00000/testTag com.byrai...mple_001 I 接收到的指定启动模式的参数值1 02-21 16:42:30.032 21526-21526 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onNewWant 02-21 16:42:30.693 21526-21526 A00000/testTag com.byrai...mple_001 I 接收到的指定启动模式的参数值1 02-21 16:42:30.701 21526-21526 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onNewWant

可以看到后面再次启动时候则走的SpecifiedAbility回调onNewWant,通过aa工具查看,只有2个UIAbility

$ aa dump -l User ID #100 current mission lists:{ Mission ID #142 mission name #[#com.byrain.example_001:entry:EntryAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1765 app name [com.byrain.example_001] main name [EntryAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #BACKGROUND start time [101033688] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false } Mission ID #143 mission name #[#com.byrain.example_001:entry:SpecifiedAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1766 app name [com.byrain.example_001] main name [SpecifiedAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #FOREGROUND start time [101035574] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false }

我们再次重新启动应用,点击打开指定模式为多实例窗口,在打开的新页面再次点击,看日志:

02-21 16:52:12.299 23949-23949 A00000/testTag pid-23949 I EntryAbility onCreate 02-21 16:52:12.314 23949-23949 A00000/testTag com.byrai...mple_001 I EntryAbility onWindowStageCreate 02-21 16:52:12.329 23949-23949 A00000/testTag com.byrai...mple_001 I EntryAbility onForeground 02-21 16:52:12.374 23949-23949 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content. 02-21 16:52:14.130 23949-23949 A00000/testTag com.byrai...mple_001 I 启动页面类型值2 02-21 16:52:14.136 23949-23949 A00000/testTag com.byrai...mple_001 I 接收到的指定启动模式的参数值2 02-21 16:52:14.161 23949-23949 A00000/testTag com.byrai...mple_001 I EntryAbility onBackground 02-21 16:52:14.167 23949-23949 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onCreate 02-21 16:52:14.179 23949-23949 A00000/testTag com.byrai...mple_001 I specifiedability onWindowStageCreate 02-21 16:52:14.182 23949-23949 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onForeground 02-21 16:52:14.199 23949-23949 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content. 02-21 16:52:15.209 23949-23949 A00000/testTag com.byrai...mple_001 I 启动页面类型值3 02-21 16:52:15.213 23949-23949 A00000/testTag com.byrai...mple_001 I 接收到的指定启动模式的参数值3 02-21 16:52:15.234 23949-23949 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onBackground 02-21 16:52:15.247 23949-23949 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onCreate 02-21 16:52:15.254 23949-23949 A00000/testTag com.byrai...mple_001 I specifiedability onWindowStageCreate 02-21 16:52:15.256 23949-23949 A00000/testTag com.byrai...mple_001 I SpecifiedAbility onForeground 02-21 16:52:15.293 23949-23949 A00000/testTag com.byrai...mple_001 I Succeeded in loading the content.

同样启动SpecifiedAbility,这时每次点击都会创建一个新实例,aa查看有3个UIAbility实例

$ aa dump -l User ID #100 current mission lists:{ Mission ID #144 mission name #[#com.byrain.example_001:entry:EntryAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1777 app name [com.byrain.example_001] main name [EntryAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #BACKGROUND start time [101618688] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false } Mission ID #145 mission name #[#com.byrain.example_001:entry:SpecifiedAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1778 app name [com.byrain.example_001] main name [SpecifiedAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #BACKGROUND start time [101620679] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false } Mission ID #146 mission name #[#com.byrain.example_001:entry:SpecifiedAbility] lockedState #0 mission affinity #[] AbilityRecord ID #1779 app name [com.byrain.example_001] main name [SpecifiedAbility] bundle name [com.byrain.example_001] ability type [PAGE] state #FOREGROUND start time [101621751] app state #FOREGROUND ready #1 window attached #0 launcher #0 callee connections: isKeepAlive: false }

以上就是UIAbility启动模式介绍,欢迎点赞、关注+收藏


__EOF__

本文作者拜雨
本文链接https://www.cnblogs.com/baiyuas/p/18729560.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   拜雨  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示