浅谈 OpenHarmony 中北向应用实现页面跳转的几种方式
本文将介绍 OpenHarmony 中北向应用实现页面跳转的几种方式,涵盖了目前 (OpenHarmony v3.2) 常见的所有方法,开发者可以根据场景需求自行选择。
OpenHarmony 迭代迅速,版本间差异巨大。实际开发时,请确认设备的支持能力以及官方最新文档。
页面路由
@ohos.router (页面路由) 本模块从 API Version 8 开始支持。
@system.router (页面路由) 自 API Version 8 开始,该接口不再维护,推荐使用新接口 @ohos.router。
这种方式只适用于在单一 Ability 内部的页面间跳转,不支持跨 Ability。
但这种方式的使用场景十分常见,例如点击查看详情 (router.push) 并返回 (router.back)。
导入模块
import router from '@ohos.router'@ohos.router 模块中最常用的就是 router.push、router.back 和 router.getParams。
router.push用于跳转到应用内的指定页面。router.back返回上一页面或指定的页面。router.getParams获取发起跳转的页面往当前页传入的参数。
除此之外,某些情况下也会使用 router.clear。(清空页面栈中的所有历史页面,仅保留当前页面作为栈顶页面)
完整示例请见 GitHub 仓库,如果文章对您有所帮助的话,不妨点个 Star 再走。
// MainAbility Index Page
import router from '@ohos.router';
async routePage(url: string, params = {}) {
let options = {
url: url,
params: params
}
try {
await router.push(options)
} catch (err) {
console.info(`Fail in routePage(), code: ${err.code}, msg: ${err.msg}`)
}
}
......
@Entry
@Component
struct Index {
abilityName: string
pageName: string
......
.onClick(() => this.routePage('pages/param', { data: `Route From ${this.abilityName} ${this.pageName}` }))
······
}// MainAbility Param Page
import router from '@ohos.router';
......
@Entry
@Component
struct Index {
@State data: number | string = router.getParams()['data']
......
.onClick(() => router.back())
······
}若你使用 DevEco Studio 进行开发(大概没有人不用),请在侧边栏中右键选择 New ⇨ Page 新建页面。通过这种方式,DevEco Studio 将自动配置好 config.json。
若你选择手动创建新页面,请参考 应用包结构说明(FA 模型)和应用包结构说明(Stage 模型)自行配置 config.json 文件。
router.push 和 router.back 接受的参数格式都为 RouterOptions。
url为目标页面的绝对路径,其中若该值为"/",则跳转到首页。params为跳转时要同时传递到目标页面的数据,目标页面可通过router.getParams获取发起跳转的页面往当前页传入的参数。
FeatureAbility 模块
在旧的 FA 模型中,使用 @ohos.ability.featureAbility 模块。
在新的 Stage 模型中,使用 @ohos.application.Ability 模块。
这种方式只适用于在不同 Ability 间跳转。
导入模块
import featureAbility from '@ohos.ability.featureAbility'该模块提供了丰富的能力,包括启动新的 Ability、获取 dataAbilityHelper、设置此 Page Ability、获取当前 Ability 对应的窗口,连接服务等。
这里,我们只会用到 featureAbility.startAbility 和 featureAbility.getWant。
featureAbility.startAbility用于启动新的 Ability。featureAbility.getWant用于获取从 Ability 发送的 Want。
除此之外,featureAbility.terminateSelf 和 featureAbility.terminateSelfWithResult 也是十分实用的 API。
完整示例请见 GitHub 仓库,如果文章对您有所帮助的话,不妨点个 Star 再走。
// MainAbility Index Page
import featureAbility from '@ohos.ability.featureAbility';
async startAbility(bundleName: string, abilityName: string, parameters = {}) {
let want = {
bundleName: bundleName,
abilityName: abilityName,
parameters: parameters
}
try {
await featureAbility.startAbility({ want: want });
} catch (err) {
console.info(`Fail in startAbility(), code: ${err.code}, msg: ${err.msg}`)
}
}
......
@Entry
@Component
struct Index {
abilityName: string
pageName: string
......
.onClick(() => this.startAbility('com.github.hydrotho.router', 'com.example.entry.SecondAbility', { url: 'pages/second', isPassingData: true }))
······
}// SecondAbility Second Page
import featureAbility from '@ohos.ability.featureAbility';
async startAbility(bundleName: string, abilityName: string, parameters = {}) {
let want = {
bundleName: bundleName,
abilityName: abilityName,
parameters: parameters
}
try {
await featureAbility.startAbility({ want: want });
} catch (err) {
console.info(`Fail in startAbility(), code: ${err.code}, msg: ${err.msg}`)
}
}
......
@Entry
@Component
struct Index {
abilityName: string
pageName: string
@State isPassingData: boolean = false
......
async getWant() {
let want = await featureAbility.getWant()
if (!want) {
return
}
if (want.parameters.isPassingData === true) {
this.isPassingData = want.parameters.isPassingData
}
}
aboutToAppear() {
this.getWant()
}
······
.onClick(() => this.startAbility('com.github.hydrotho.router', 'com.example.entry.MainAbility'))
······
}若你使用 DevEco Studio 进行开发(大概没有人不用),请在侧边栏右键菜单中新建 Ability 和 Page。通过这种方式,DevEco Studio 将自动配置好 config.json。
若你选择手动创建新页面,请参考 应用包结构说明(FA 模型)和应用包结构说明(Stage 模型)自行配置 config.json 文件。
这种方法使用时的关键在于 featureAbility.startAbility 接受的 Want 类型参数。
bundleName其实就是config.json中app里的bundleName属性所对应的值,也就是新建北向应用工程时输入的 Bundle Name。abilityName值的构成为package+ Ability Name。package为config.json中module里的package属性所对应的值。parameters由开发者自行决定传入的键值对,例如目标页面不为其所在的 Ability 的默认页面时,传入url指定目标页面。默认会携带以下键值:ohos.aafwk.callerPid表示拉起方的 pid。ohos.aafwk.param.callerToken表示拉起方的 token。ohos.aafwk.param.callerUid表示发起方的 uid。
在许多网络上的教程以及官方文档中,bundleName 与 package 的值相同,导致人们误解以为 abilityName 的前缀为 bundleName 实际上并不是如此。
例如官方开发指导文档中的这段代码
import featureAbility from '@ohos.ability.featureAbility';
let promise = featureAbility.startAbility (
{
want:
{
bundleName: "com.jstest.service",
abilityName: "com.jstest.service.ServiceAbility",
},
}
);看似 bundleName 与 abilityName 的前缀相同,其实只不过是这里 bundleName 与 package 的值相同。
初学者如果理不清这些概念,待到实际开发时,这就是个大坑。
在 @ohos.router 模块中,我们直接使用 RouterOptions 类型里的 url 属性指定目标页面。
而在 @ohos.ability.featureAbility 模块中,Want 类型里也有到看似类似的属性 uri。初学者容易想当然地使用 uri 指定目标 Ability 的目标页面,这是不对的。实际上我们需要将目标页面地址包裹在 parameters 属性中,键名为 url。
若进行页面跳转时携带了数据,目标页面可以在页面生命周期的早期调用 featureAbility.getWant() 获取源页面跳转时所传递的数据。
关于页面的生命周期,OpenHarmony 中 JS 语言和 eTS 语言有所不同,请参考 JS 语言页面生命周期函数和 eTS 语言页面生命周期函数。
例如,可以在 eTS 语言中的 aboutToAppear 生命周期函数中调用 featureAbility.getWant() 在页面显示前获取传递的数据,对页面进行调整。
WantAgent 模块
这种方式只适用于在不同 Ability 间跳转。
导入模块
import WantAgent from '@ohos.wantAgent';WantAgent 模块提供了触发、取消、比较 WantAgent 实例等能力。
WantAgent 不仅可以开启 Ability,还可以发送公共事件,其行为可以通过 OperationType 操控。这里我们只使用 START_ABILITY。
完整示例请见 GitHub 仓库,如果文章对您有所帮助的话,不妨点个 Star 再走。
// MainAbility Index Page
import wantAgent from '@ohos.wantAgent';
startAbilityViaWantAgent(bundleName: string, abilityName: string) {
let wantAgentInfo = {
wants: [
{
bundleName: bundleName,
abilityName: abilityName
}
],
operationType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
wantAgentFlags: [wantAgent.WantAgentFlags.CONSTANT_FLAG]
}
wantAgent.getWantAgent(wantAgentInfo, (error, wantAgentObj) => {
if (error.code) {
console.error("[WantAgent]getWantAgent error: " + JSON.stringify(error))
} else {
console.log("[WantAgent]getWantAgent success")
let triggerInfo = {
code: 0
}
wantAgent.trigger(wantAgentObj, triggerInfo, (completeData) => {
console.log("[WantAgent]getWantAgent success, completeData: ", +JSON.stringify(completeData))
})
}
})
}
......
@Entry
@Component
struct Index {
abilityName: string
pageName: string
......
.onClick(() => this.startAbilityViaWantAgent('com.github.hydrotho.router', 'com.example.entry.WantAgentAbility'))
······
}若你使用 DevEco Studio 进行开发(大概没有人不用),请在侧边栏右键菜单中新建 Ability 和 Page。通过这种方式,DevEco Studio 将自动配置好 config.json。
若你选择手动创建新页面,请参考 应用包结构说明(FA 模型)和应用包结构说明(Stage 模型)自行配置 config.json 文件。
这里的 wants 属性也是 Want 类型,具体注意事项请见上文。
WantAgent 模块一般还是其公共事件功能 (SEND_COMMON_EVENT) 较为常用,更多功能请参考官方文档。
总结
本文介绍了目前 (OpenHarmony v3.2) 北向应用实现页面跳转常见的所有方法,开发者可以根据场景需求自行选择。
一般来说,我们可以这样选择:
- 若使用场景为同一 Ability 内部的不同页面间跳转,选择
@ohos.router模块。 - 若使用场景为不同 Ability 间跳转,选择
@ohos.ability.featureAbility模块(FA 模型)或@ohos.application.Ability模块(Stage 模型)。
