「鸿蒙」应用程序入口-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@Componentstruct 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@Componentstruct Index {  @State src: string = '';  onPageShow() {    this.src = router.getParams()?.['src'];  }  // 页面刷新展现  ...}

成果示意图如下图所示。在Second页面中,点击“Back”后,即可从Second页面返回到Index页面,并在Index页面中接管参数和进行页面刷新展现。

UIAbility的生命周期

当用户浏览、切换和返回到对应利用的时候,利用中的UIAbility实例会在其生命周期的不同状态之间转换。

UIAbility类提供了很多回调,通过这些回调能够通晓以后UIAbility的某个状态曾经产生扭转:例如UIAbility的创立和销毁,或者UIAbility产生了前后台的状态切换。

为了实现多设施状态上的裁剪和多窗口的可扩展性,系统对组件治理和窗口治理进行理解耦。UIAbility的生命周期包含CreateForegroundBackgroundDestroy四个状态,WindowStageCreateWindowStageDestroy为窗口管理器(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启动模式的开发应用的步骤如下所示。

  1. 在module.json5文件中的“launchType”字段配置为“specified”。

    {"module": {  ...  "abilities": [    {      "launchType": "specified",      ...    }  ]  }}
  2. 在调用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的AbilityContextcontext.startAbility(want).then(() => { ...}).catch((err) => { ...})
  3. 在被拉起方UIAbility对应的AbilityStage的onAcceptWant生命周期回调中,解析传入的want参数,获取“instanceKey”自定义参数。依据业务须要返回一个该UIAbility实例的字符串Key标识。如果之前启动过此Key标识的UIAbility,则会将之前的UIAbility拉回前台并获焦,而不创立新的实例,否则创立新的实例并启动。

    onAcceptWant(want): string { // 在被启动方的AbilityStage中,针对启动模式为specified的UIAbility返回一个UIAbility实例对应的一个Key值 // 以后示例指的是device Module的EntryAbilityif (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...