「鸿蒙」应用程序入口 -UIAbility
UIAbility 是一种蕴含用户界面的利用组件,次要用于和用户进行交互。UIAbility 也是系统调度的单元,为利用提供窗口在其中绘制界面。
每一个 UIAbility 实例,都对应于一个最近工作列表中的工作。
一个利用 能够有一个 UIAbility,也能够有多个 UIAbility,如下图所示。例如浏览器利用能够通过一个 UIAbility 联合多页面的模式让用户进行的搜寻和浏览内容;而聊天利用减少一个“外卖性能”的场景,则能够将聊天利用中“外卖性能”的内容独立为一个 UIAbility,当用户关上聊天利用的“外卖性能”,查看外卖订单详情,此时有新的聊天音讯,即能够通过最近工作列表切换回到聊天窗口持续进行聊天对话。
一个 UIAbility 能够对应于多个页面,倡议将一个独立的功能模块放到一个 UIAbility 中,以多页面的模式出现。例如新闻利用在浏览内容的时候,能够进行多页面的跳转应用。
UIAbility 内页面的跳转和数据传递
UIAbility 的数据传递包含有 UIAbility 内页面的跳转和数据传递、UIAbility 间的数据跳转和数据传递。
页面间的导航能够通过页面路由 router 模块来实现。页面路由模块依据页面 url 找到指标页面,从而实现跳转。通过页面路由模块,能够应用不同的 url 拜访不同的页面,包含跳转到 UIAbility 内的指定页面、用 UIAbility 内的某个页面替换以后页面、返回上一页面或指定的页面等。具体应用办法请参见 ohos.router (页面路由)。
页面跳转和参数接管
在应用页面路由之前,须要先导入 router 模块,如下代码所示。
import router from '@ohos.router';
页面跳转的几种形式,依据须要抉择一种形式跳转即可。
- 形式一:API9 及以上,router.pushUrl() 办法新增了 mode 参数,能够将 mode 参数配置为 router.RouterMode.Single 单实例模式 和 router.RouterMode.Standard 多实例模式。
在单实例模式下:如果指标页面的 url 在页面栈中曾经存在同 url 页面,离栈顶最近同 url 页面会被挪动到栈顶,挪动后的页面为新建页,原来的页面依然存在栈中,页面栈的元素数量不变;如果指标页面的 url 在页面栈中不存在同 url 页面,按多实例模式跳转,页面栈的元素数量会加 1。
阐明
当页面栈的元素数量较大或者超过 32 时,能够通过调用 router.clear()办法革除页面栈中的所有历史页面,仅保留以后页面作为栈顶页面。
router.pushUrl({
url: 'pages/Second',
params: {src: 'Index 页面传来的数据',}
}, router.RouterMode.Single)
-
形式二:API9 及以上,router.replaceUrl() 办法新增了 mode 参数,能够将 mode 参数配置为 router.RouterMode.Single 单实例模式 和 router.RouterMode.Standard 多实例模式。
在单实例模式下:如果指标页面的 url 在页面栈中曾经存在同 url 页面,离栈顶最近同 url 页面会被挪动到栈顶,替换以后页面,并销毁被替换的以后页面,挪动后的页面为新建页,页面栈的元素数量会减 1;如果指标页面的 url 在页面栈中不存在同 url 页面,按多实例模式跳转,页面栈的元素数量不变。router.replaceUrl({ url: 'pages/Second', params: {src: 'Index 页面传来的数据',} }, router.RouterMode.Single)
曾经实现了页面的跳转,接下来,在 Second 页面中如何进行自定义参数的接管呢?
通过调用 router.getParams() 办法获取 Index 页面传递过去的自定义参数。
import router from '@ohos.router';
@Entry
@Component
struct Second {@State src: string = router.getParams()?.['src'];
// 页面刷新展现
...
}
成果示意如下图所示。在 Index 页面中,点击“Next”后,即可从 Index 页面跳转到 Second 页面,并在 Second 页面中接管参数和进行页面刷新展现。
页面返回和参数接管
常常还会遇到一个场景,在 Second 页面中,实现了一些性能操作之后,心愿能返回到 Index 页面,那咱们要如何实现呢?
在 Second 页面中,能够通过调用 router.back() 办法实现返回到上一个页面,或者在调用 router.back()办法时减少可选的 options 参数(减少 url 参数)返回到指定页面。
阐明
- 调用 router.back()返回的指标页面须要在页面栈中存在能力失常跳转。
- 例如调用 router.pushUrl()办法跳转到 Second 页面,在 Second 页面能够通过调用 router.back()办法返回到上一个页面。
- 例如调用 router.clear()办法清空了页面栈中所有历史页面,仅保留以后页面,此时则无奈通过调用 router.back()办法返回到上一个页面。
-
返回上一个页面。
router.back();
-
返回到指定页面。
router.back({url: 'pages/Index'});
成果示意如下图所示。在 Second 页面中,点击“Back”后,即可从 Second 页面返回到 Index 页面。
页面返回能够依据业务须要减少一个询问对话框。
即在调用 router.back()办法之前,能够先调用 router.enableBackPageAlert()办法开启页面返回询问对话框性能。
阐明
- router.enableBackPageAlert() 办法开启页面返回询问对话框性能,只针对以后页面失效。例如在调用 router.pushUrl()或者 router.replaceUrl()办法,跳转后的页面均为新建页面,因而在页面返回之前均须要先调用 router.enableBackPageAlert()办法之后,页面返回询问对话框性能才会失效。
- 如需敞开页面返回询问对话框性能,能够通过调用 router.disableAlertBeforeBackPage() 办法敞开该性能即可。
router.enableBackPageAlert({message: 'Message Info'});
router.back();
在 Second 页面中,调用 router.back()办法返回上一个页面或者返回指定页面时,依据须要持续减少自定义参数,例如在返回时减少一个自定义参数 src。
router.back({
url: 'pages/Index',
params: {src: 'Second 页面传来的数据',}
})
从 Second 页面返回到 Index 页面。在 Index 页面通过调用 router.getParams()办法,获取 Second 页面传递过去的自定义参数。
阐明
调用 router.back()办法,不会新建页面 ,返回的是原来的页面,在 原来页面中 @State 申明的变量不会反复申明 ,以及 也不会触发页面的 aboutToAppear()生命周期回调 ,因而无奈间接在变量申明以及页面的 aboutToAppear() 生命周期回调中接管和解析 router.back()传递过去的自定义参数。
能够放在业务须要的地位进行参数解析。示例代码在 Index 页面中的 onPageShow()生命周期回调中进行参数的解析。
import router from '@ohos.router';
@Entry
@Component
struct Index {
@State src: string = '';
onPageShow() {this.src = router.getParams()?.['src'];
}
// 页面刷新展现
...
}
成果示意图如下图所示。在 Second 页面中,点击“Back”后,即可从 Second 页面返回到 Index 页面,并在 Index 页面中接管参数和进行页面刷新展现。
UIAbility 的生命周期
当用户浏览、切换和返回到对应利用的时候,利用中的 UIAbility 实例会在其生命周期的不同状态之间转换。
UIAbility 类提供了很多回调,通过这些回调能够通晓以后 UIAbility 的某个状态曾经产生扭转:例如 UIAbility 的创立和销毁,或者 UIAbility 产生了前后台的状态切换。
为了实现多设施状态上的裁剪和多窗口的可扩展性,系统对组件治理和窗口治理进行理解耦。UIAbility 的生命周期包含 Create、Foreground、Background、Destroy 四个状态,WindowStageCreate和 WindowStageDestroy 为窗口管理器(WindowStage)在 UIAbility 中治理 UI 界面性能的两个生命周期回调,从而 实现 UIAbility 与窗口之间的弱耦合。如下图所示。
Create
Create 状态,在 UIAbility 实例创立时触发,零碎会调用 onCreate 回调。能够在 onCreate 回调中进行相干初始化操作。
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {onCreate(want, launchParam) {
// 利用初始化
...
}
...
}
WindowStageCreate
UIAbility 实例创立实现之后,在进入 Foreground 之前,零碎会创立一个 WindowStage。每一个 UIAbility 实例都对应持有一个 WindowStage 实例。
WindowStage 为本地窗口管理器,用于治理窗口相干的内容,例如与界面相干的获焦 / 失焦、可见 / 不可见。
能够在 onWindowStageCreate 回调中,设置 UI 页面加载、设置 WindowStage 的事件订阅。
在 onWindowStageCreate(windowStage)中通过 loadContent 接口设置利用要加载的页面,Window 接口的应用详见窗口开发领导。
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
...
onWindowStageCreate(windowStage: window.WindowStage) {
// 设置 UI 页面加载
// 设置 WindowStage 的事件订阅(获焦 / 失焦、可见 / 不可见)...
windowStage.loadContent('pages/Index', (err, data) => {...});
}
...
}
例如用户关上游戏利用,正在打游戏的时候,有一个音讯告诉,关上音讯,音讯会以弹窗的模式弹出在游戏利用的上方,此时,游戏利用就从获焦切换到了失焦状态,音讯利用切换到了获焦状态。对于音讯利用,在 onWindowStageCreate 回调中,会触发获焦的事件回调,能够进行设置音讯利用的背景色彩、高亮等操作。
Foreground 和 Background
Foreground 和 Background 状态,别离在 UIAbility 切换至 前台 或者切换至 后盾 时触发。
别离对应于 onForeground 回调和 onBackground 回调。
- onForeground 回调,在 UIAbility 的 UI 页面可见之前,即 UIAbility 切换至前台时触发。能够在 onForeground 回调中申请零碎须要的资源,或者从新申请在 onBackground 中开释的资源。
-
onBackground 回调,在 UIAbility 的 UI 页面齐全不可见之后,即 UIAbility 切换至后盾时候触发。能够在 onBackground 回调中开释 UI 页面不可见时无用的资源,或者在此回调中执行较为耗时的操作,例如状态保留等。
import UIAbility from '@ohos.app.ability.UIAbility'; import window from '@ohos.window'; export default class EntryAbility extends UIAbility { ... onForeground() { // 申请零碎须要的资源,或者从新申请在 onBackground 中开释的资源 ... } onBackground() { // 开释 UI 页面不可见时无用的资源,或者在此回调中执行较为耗时的操作 // 例如状态保留等 ... } }
例如用户关上地图利用查看以后地理位置的时候,假如地图利用已取得用户的定位权限受权。在 UI 页面显示之前,能够在 onForeground 回调中关上定位性能,从而获取到以后的地位信息。
当地图利用切换到后盾状态,能够在 onBackground 回调中进行定位性能,以节俭零碎的资源耗费。
WindowStageDestroy
对应于 onWindowStageCreate 回调。在 UIAbility 实例销毁之前,则会先进入 onWindowStageDestroy 回调,咱们能够在该回调中开释 UI 页面资源。
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
...
onWindowStageDestroy() {
// 开释 UI 页面资源
...
}
}
例如在 onWindowStageCreate 中设置的获焦 / 失焦等 WindowStage 订阅事件。
Destroy
Destroy 状态,在 UIAbility 销毁时触发。能够在 onDestroy 回调中进行系统资源的开释、数据的保留等操作。
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
export default class EntryAbility extends UIAbility {
...
onDestroy() {
// 系统资源的开释、数据的保留等
...
}
}
例如用户应用利用的程序退出性能,会调用 UIAbilityContext 的 terminalSelf()办法,从而实现 UIAbility 销毁。或者用户应用最近工作列表敞开该 UIAbility 实例时,也会实现 UIAbility 的销毁。
UIAbility 的启动模式
对于浏览器或者新闻等利用,用户在关上该利用,并浏览拜访相干内容后,回到桌面,再次关上该利用,显示的依然是用户以后拜访的界面。
对于利用的分屏操作,用户心愿应用两个不同利用(例如备忘录利用和图库利用)之间进行分屏,也心愿能应用同一个利用(例如备忘录利用本身)进行分屏。
对于文档利用,用户从文档利用中关上一个文档内容,回到文档利用,持续关上同一个文档,心愿关上的还是同一个文档内容。
基于以上场景的思考,UIAbility 以后反对 3 种启动模式:
- singleton(单实例模式)
- multiton(多实例模式)
- specified(指定实例模式)
对启动模式的具体阐明如下:
singleton(单实例模式)
当用户关上浏览器或者新闻等利用,并浏览拜访相干内容后,回到桌面,再次关上该利用,显示的依然是用户以后拜访的界面。
这种状况下能够将 UIAbility 配置为 singleton(单实例模式)。每次调用 startAbility()办法时,如果利用过程中该类型的 UIAbility 实例曾经存在,则复用零碎中的 UIAbility 实例,零碎中只存在惟一一个该 UIAbility 实例。
即在最近工作列表中只存在一个该类型的 UIAbility 实例。
singleton 启动模式,也是默认状况下的启动模式。
singleton 启动模式,每次调用 startAbility()启动 UIAbility 时,如果利用过程中该类型的 UIAbility 实例曾经存在,则复用零碎中的 UIAbility 实例,零碎中只存在惟一一个该 UIAbility 实例。
singleton 启动模式的开发应用,在 module.json5 文件中的“launchType”字段配置为“singleton”即可。
{
"module": {
...
"abilities": [
{
"launchType": "singleton",
...
}
]
}
}
multiton(多实例模式)
用户在应用分屏性能时,心愿应用两个不同利用(例如备忘录利用和图库利用)之间进行分屏,也心愿能应用同一个利用(例如备忘录利用本身)进行分屏。
这种状况下能够将 UIAbility 配置为 multiton(多实例模式)。每次调用 startAbility()办法时,都会在利用过程中创立一个该类型的 UIAbility 实例。
即在最近工作列表中能够看到有多个该类型的 UIAbility 实例。
multiton 启动模式,每次调用 startAbility()办法时,都会在利用过程中创立一个该类型的 UIAbility 实例。
multiton 启动模式的开发应用,在 module.json5 文件中的“launchType”字段配置为“multiton”即可。
{
"module": {
...
"abilities": [
{
"launchType": "multiton",
...
}
]
}
}
specified(指定实例模式)
用户打开文档利用,从文档利用中关上一个文档内容,回到文档利用,持续关上同一个文档,心愿关上的还是同一个文档内容;以及在文档利用中新建一个新的文档,每次新建文档,心愿关上的都是一个新的空白文档内容。
这种状况下能够将 UIAbility 配置为 specified(指定实例模式)。在 UIAbility 实例新创建之前,容许开发者为该实例创立一个字符串 Key,新创建的 UIAbility 实例绑定 Key 之后,后续每次调用 startAbility 办法时,都会询问利用应用哪个 Key 对应的 UIAbility 实例来响应 startAbility 申请。如果匹配有该 UIAbility 实例的 Key,则间接拉起与之绑定的 UIAbility 实例,否则创立一个新的 UIAbility 实例。运行时由 UIAbility 外部业务决定是否创立多实例。
specified 启动模式,依据业务须要是否创立一个新的 UIAbility 实例。在 UIAbility 实例创立之前,会先进入 AbilityStage 的 onAcceptWant 回调,在 onAcceptWant 回调中为每一个 UIAbility 实例创立一个 Key,后续每次调用 startAbility()办法创立该类型的 UIAbility 实例都会询问应用哪个 Key 对应的 UIAbility 实例来响应 startAbility()申请。
specified 启动模式的开发应用的步骤如下所示。
-
在 module.json5 文件中的“launchType”字段配置为“specified”。
{ "module": { ... "abilities": [ { "launchType": "specified", ... } ] } }
-
在调用 startAbility()办法的 want 参数中,减少一个自定义参数来区别 UIAbility 实例,例如减少一个“instanceKey”自定义参数。
// 在启动指定实例模式的 UIAbility 时,给每一个 UIAbility 实例配置一个独立的 Key 标识 function getInstance() {...} let want = { deviceId: "", // deviceId 为空示意本设施 bundleName: "com.example.myapplication", abilityName: "MainAbility", moduleName: "device", // moduleName 非必选,默认为以后 UIAbility 所在的 Module parameters: { // 自定义信息 instanceKey: getInstance(),}, } // context 为启动方 UIAbility 的 AbilityContext context.startAbility(want).then(() => {...}).catch((err) => {...})
-
在被拉起方 UIAbility 对应的 AbilityStage 的 onAcceptWant 生命周期回调中,解析传入的 want 参数,获取“instanceKey”自定义参数。依据业务须要返回一个该 UIAbility 实例的字符串 Key 标识。如果之前启动过此 Key 标识的 UIAbility,则会将之前的 UIAbility 拉回前台并获焦,而不创立新的实例,否则创立新的实例并启动。
onAcceptWant(want): string { // 在被启动方的 AbilityStage 中,针对启动模式为 specified 的 UIAbility 返回一个 UIAbility 实例对应的一个 Key 值 // 以后示例指的是 device Module 的 EntryAbility if (want.abilityName === 'MainAbility') {return `DeviceModule_MainAbilityInstance_${want.parameters.instanceKey}`; } return ''; }
例如在文档利用中,能够对不同的文档实例内容绑定不同的 Key 值。当每次新建文档的时候,能够传入不同的新 Key 值(如能够将文件的门路作为一个 Key 标识),此时 AbilityStage 中启动 UIAbility 时都会创立一个新的 UIAbility 实例;当新建的文档保留之后,回到桌面,或者新关上一个已保留的文档,回到桌面,此时再次关上该已保留的文档,此时 AbilityStage 中再次启动该 UIAbility 时,关上的依然是之前原来已保留的文档界面。
参考
- https://developer.huawei.com/consumer/cn/training/course/slig…