HarmonyOS RN 项目中页面返回事件的自定义处理
RN HarmonyOS项目中,假如 RN 内使用了 Navigation,那么 RN 内的路由返回会和原生路由返回产生冲突,默认情况下返回可以分为两种情况:
- 从 RN Navigation 的根页面返回;
- 从 RN Navigation 的子页面返回。
第1种情况下,会执行默认的 Router 或 Navigation 的返回逻辑;第2种情况下,正常逻辑应该返回 RN Navigation 栈内的上一个页面,但实际上会发现,此时会直接返回上一个原生页面(如果当前页面非路由栈根页面),并未走 RN Navigation 内部的返回逻辑。
原生侧的路由架构又分为 Router 和 Navigation 两种场景,需要根据实际情况进行处理。
1.调用 rnohCoreContext.dispatchBackPress()
为了触发 RN Navigation 内部的返回逻辑,需要在原生 RN 容器页面的返回方法中调用 this.rnohCoreContext!.dispatchBackPress(),如果使用的是 Router:
onBackPress(): boolean | undefined {
this.rnohCoreContext!.dispatchBackPress()
return true
}
如果使用的是原生 Navigation:
NavDestination() {
...
}
.onBackPressed(() => {
this.rnohCoreContext!.dispatchBackPress();
return true;
}
2. dispatchBackPress 的执行流程
调用了 rnohCoreContext!.dispatchBackPress() 虽然能够正常执行 RN Navigation 内的返回逻辑,但是此时从 RN Navigation 首页侧滑会直接退出应用,这是因为执行了 dispatchBackPress 的默认行为,这显然不是我们想要的效果,因此我们要修改 spatchBackPress 的实现逻辑。
首先让我们梳理一下 rnohCoreContext!.dispatchBackPress() 的执行流程:
- rnohCoreContext.dispatchBackPress()
- rnInstance.onBackPress()
- rnohContext.invokeDefaultBackPressHandler()
- rnInstanceImpl.backPressHandler() 或 rnAbility.defaultBackPressHandler()
其中第3、4步,只有从 RN Navigation 首页返回时才会触发。所以此时不做进一步处理 RN Navigation 内部的返回逻辑也会正常执行。
第4步中,如果在创建 RNInstance 时实现了它的 backPressHandler,就会执行 backPressHandler;否则,会执行 rnAbility.defaultBackPressHandler()。因此,有两种方法可以自定义 RN Navigation 首页的返回事件。
根据上面的分析,可以总结返回事件的处理方法如下:
Router 场景:1)在 EntryAbility 中重写 RNAbility 的 defaultBackPressHandler,执行 router.back(); 2)或者在 RNInstance 的 backPressHandler 中执行 router.back()。
Navigation 场景:在 RNInstance 的 backPressHandler 中执行 this.pagePaths.pop(),pagePaths 是 Navigation 的路由栈。