RN踩坑心得第三弹,导入 React Navigation 实现页面跳转

前言

此篇心得是RN开发心得的第三篇,在之前第一篇

RN开发初探与踩坑心得_rn编程-CSDN博客

初步搭了一个可运行的RN项目,但是之前那篇的搭建仅仅是可运行,但在导入一些库后发现之前的方式版本兼容性很差,导个库就运行不了。在经过一番的尝试探索后,将心得整理成这一篇。

此次目标是要实现页面跳转,以及实现页面传参。但是在引入依赖库的过程遇到不少问题,所以此篇的重点就是解决这些问题。

RN官方推荐使用React Navigation

使用导航器跳转页面 · React Native 中文网

Getting started | React Navigation

先按官方的指导,先引入所需的库

yarn add @react-navigation/native

yarn add react-native-screens react-native-safe-area-context

此时还未指定库的版本,下图是2024/06/12默认拉到的最新版本

拉完版本后,直接用我的Android Studio 3.6.1,gradle-5.6.4运行,报了以下错误

此时我的gradle版本已经无法编译此版本的三方库了

以下我尝试了很多配置,将心得整理在下方

问题处理

在尝试过程,有一些关于AS、Gradle版本切换的尝试,但Gradle有哪些版本可用,该尝试哪些关键性的版本呢?

关于AS与Gradle的版本对照关系,我参考下面这篇是比较详细的

Android studio版本对用的gradle版本和插件版本(注意事项)_gradle版本和gradle插件版本-CSDN博客

尝试1: 先降报错的库的版本

选择一个参考别人项目中的版本

问题1: 导入的库(react-native-safe-area-context等)找不到rn库的类。

这个问题在我的踩坑第一篇也遇到过,app/build.gradle 引入rn库的方式,官方教程是

implementation "com.facebook.react:react-native:+"

但我用这种方式无法正确导入库,就是 BUILD SUCCESSFUL 但代码中无法引用库中的类,External Libraries也找不到相关的库。

后来指定版本

implementation "com.facebook.react:react-native:0.68.1"

之后就能找到库了,那时以为是没使用 React Native Gradle Plugin 插件的原因,后来发现不是,后面说明。

尝试2: 手动指定导入库的rn版本

因为之前有处理过这个问题,所以我尝试将 node_modules\react-native-safe-area-context\android 及 node_modules\react-native-screens\android 下的 build.gradle 的 react-native:+ 都手动指定版本号0.68.1

改完后编译项目,确实能成功了。

但是,官方建议:node_modules/目录中(这个目录我们原则上不复制、不移动、不修改、不上传,随用随装)

用这种方式处理后只能暂时在此次环境运行,如果用git在别处导下来,还得改一遍。又或是又导入别的库后,这些改过的又还原了,有得再改一遍。所以现在目标需要找到 react-native:+ 无法引入的真正的原因。

思路:先不导入导航库,先尝试在 app/build.gradle 中,用 react-native:+ 的方式正确导入RN库。

尝试3: 使用另一个较新版本的AS (Android Studio Giraffe 2022.3.1) 直接开启此项目

结果3: 还是一样找不到库

尝试4: 升级gradle-8.0(此AS创建新项目时的默认版本),插件版本7.4.2

结果4: 成功导入库,但是我的RNActivity报错了

透过观察AS导入的libraries,发现此时导入的 react-native 版本已经不是原来的0.68.1了,而是0.71.0-rc.0。

报错的 RedBoxHandler 这个类的包已经被改了,重新导包后已可正常运行。

注:这个 RedBoxHandler 是之前为了解决 Android 34的问题,使用自定的 DevSupportManagerFactory 中所带的参数,后续升级RN版本后可拿掉。

此处已有一个结论,升级AS及Gradle后,可解决这个问题。

尝试5: 降低Gradle版本为6.7.1

此版本为 AS 3.6.1 能使用的最高版本,插件版本4.2.0跟3.6.1都试过,效果一样

结果5: BUILD SUCCESSFUL,但是要编译运行时报 More than one file was found with OS independent path 的错误

加上 packagingOptions

编译成功,但是运行时报错

估计还有别的坑,就没深究下去了

由此得一结论,AS 3.6.1已经无法优雅的解决RN引入其他库的问题了,接下来我将以 AS Giraffe 2022.3.1 版本进行开发。

现在,改回gradle-8.0及插件版本,重新加回 react-native-safe-area-context 及 react-native-screens

一开始,我加回的版本是 尝试1 使用的 0.73,2.40 版本,是能直接编译运行成功的

后来我改回一开始拉到的最新版本,编译运行时出现以下错误

compileDebugJavaWithJavac' task (current target is 1.8) and 'compileDebugKotlin' task (current target is 11) jvm target compatibility should be set to the same Java version.

就是编译kotlin使用的jvm版本与java的不一致,关于此问题的解决办法

关于RN项目版本导致react-native-screens及react-native-safe-area-context报compileDebugKotlin的问题。_react-native-screens与kotlin冲突-CSDN博客

即我在android/buile.gradle 加上 kotlinVersion = '1.6.0'

加上后就编译运行成功了

我研究了一下此库的buile.gradle

就是这句代码找到主工程设置的 kotlinVersion 值

react-navigation要实现页面跳转,还要再引入一个库

yarn add @react-navigation/native-stack

注:我目前拉到的是 react-navigation 6.0系列的版本,如果是用5.0系列的版本所需要引用的库不太一样,例如:react-native-gesture-handler react-native-reanimated...,具体看官方文档。

尝试使用

基本上按着官方文档的步骤敲代码

Hello React Navigation | React Navigation

然后在模拟器上运行,结果报错了

我参考下面这个先将 screens 降版本

错误错误:找不到库“librnscreens.so”,js引擎:hermes - android - SO中文参考 - www.soinside.com

改完后终于看到带导航栏的"您好,世界!",环境搭建基本完成了。

使用心得与封装

基本的使用方法,参照官方教程,这部分是在官方基础上做一些封装,方便使用。

这个部分是按照我个人Android的开发习惯,对页面组件的理解与封装。因为我还接触不久,可能还有些片面,未来也许会有更好的封装方式。

公共 Prop 模型

这个是我在下面这个开源项目看到的(最初哪来的我不清楚)

GitHub - surmon-china/surmon.me.native: 📱 My blog app, powered by react-native

React Navigation 的官方教程是 JavaScript 写的,在实际开发中并不方便,例如 Component 中有个 props,props 中有个 navigation,navigation 有 navigate(...) 的方法。但是敲代码时不会自动提示。

加上这个props.ts后,让 Component 指定泛型 IPageProps,之后就可以在组件中输入 this.props. 后,就自动提示 navigation,以及 navigation 中可用的方法了,如此可以提升开发效率。

LifeComponent

这个 LifeComponent 是我个人的封装,主要实现 Android 中的 Activity 的生命周期。

在Android开发中,常常利用生命周期 onCreate、onResume、onPause、onDestroy 做一些事,例如:注册、注销观察者,刷新页面或释放资源等。

在RN的Component中,有 componentDidMount、componentWillUnmount 可以实现类似 onCreate、onDestroy 的功能,但 onResume、onPause 没有相应的方法。

LifeComponent 就是我为实现 onResume、onPause 所做的封装

首先,用navigation可以监听当前活动的页面

Navigation events | React Navigation

AppState可用于监听APP是在前台还是后台

AppState · React Native 中文网

实现流程

在 componentDidMount 中注册页面的 navigation.addListener('focus' 与 navigation.addListener('blur' 用以检测当前活动的页面

在活动页面 'focus' 中,注册 AppState.addEventListener('change', this.changeListener) 用以监听前后台

根据 "当前活动" 及 "前台" 的条件,可得当前页面的显示 onResume 状态,并且从前台变成 "blur" 或 "后台" 的条件,则调用 onPause

另外就是在退出时取消相应的监听

	private focusSubscription: any
    private blurSubscription: any
    private changeSubscription: any
	isResumed: boolean = false
	
	onResume() {
    }

    onPause() {
    }

    private setResumed(b: boolean) {
        if(this.isResumed != b) {
            this.isResumed = b;
            if(b) {
                this.onResume();
            } else {
                this.onPause();
            }
        }
    }

    private changeListener = (nextAppState: AppStateStatus) => {
        if (nextAppState === 'active') {
            this.setResumed(true)
        } else {
            this.setResumed(false)
        }
    }

    componentDidMount(): void {
        this.focusSubscription = this.props.navigation.addListener('focus', () => {

            this.changeSubscription = AppState.addEventListener('change', this.changeListener);
            this.setResumed(AppState.currentState === 'active');
        });
        this.focusSubscription = this.props.navigation.addListener('blur', () => {
            
            this.changeSubscription?.remove();
            this.setResumed(false);
        });

    }

    componentWillUnmount(): void {
        this.props.navigation.removeListener(this.focusSubscription);
        this.props.navigation.removeListener(this.blurSubscription);

        this.changeSubscription?.remove();
        this.setResumed(false);
    }

实际使用

到此,页面导航的基本框架就算完成了,接着就是按照项目需求实际开发页面了。

源码

RNDemo: 本项目是我个人新接触RN(React Native)开发,自己写的一个Demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值