在Android中预加载React Native jsBundle

本文介绍如何在Android应用中通过预加载React Native的jsBundle来减少白屏时间,提高用户体验。通过创建ReactRootView缓存管理器、在Activity和Fragment中预加载ReactNative,以及处理权限和局限性问题,实现RN模块的快速打开。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前段时间在项目中遇到了一个问题:从原生模块跳转到RN模块时会有一段短暂的白屏时间,特别是在低端手机更加明显。在网上搜了一圈,发现这个问题非常常见。

ReactRootView mReactRootView = createRootView();
mReactRootView.startReactApplication(mReactInstanceManager, getMainComponentName(), getLaunchOptions());

这两行代码就是白屏的主要原因。因为这两行代码把jsbundle文件读入到内存中,这个过程肯定是需要耗费一些时间的,当jsbundle文件越大,可以预见加载到内存中需要的时间就越长。
解决办法就是以空间换时间,在app启动时候,就将ReactRootView初始化出来,并缓存起来,在用的时候从缓存获取ReactRootView使用,达到秒开。
目前的React Native版本更新到了0.45.1,而网上大部分的解决方案都偏旧,但是解决思路还是一样的,不过具体的解决方法会做些修改(因为RN源码的变动)。
下面开始详细说明。

1. 创建ReactRootView缓存管理器

View缓存管理器先提前将ReactRootView初始化并用一个WeakHashMap保存。在这里需要十分小心内存泄露的问题。

public class RNCacheViewManager {
    public static Map<String, ReactRootView> CACHE;
    public static final int REQUEST_OVERLAY_PERMISSION_CODE = 1111;
    public static final String REDBOX_PERMISSION_MESSAGE =
            "Overlay permissions needs to be granted in order for react native apps to run in dev mode";

    public static ReactRootView getRootView(String moduleName) {
        if (CACHE == null) return null;
        return CACHE.get(moduleName);
    }

    public static ReactNativeHost getReactNativeHost(Activity activity) {
        return ((ReactApplication) activity.getApplication()).getReactNativeHost();
    }

    /**
    * 预加载所需的RN模块
    * @param activity 预加载时所在的Activity
    * @param launchOptions 启动参数
    * @param moduleNames 预加载模块名
    * 建议在主界面onCreate方法调用,最好的情况是主界面在应用运行期间一直存在不被关闭
    */
    public static void init(Activity activity, Bundle launchOptions, String... moduleNames) {
        if (CACHE == null) CACHE = new WeakHashMap<>();
        boolean needsOverlayPermission = false;
        if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(activity)) {
            needsOverlayPermission = true;
            Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + activity.getPackageName()));
            FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);
            Toast.makeText(activity, REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();
            activity.startActivityForResult(serviceIntent, REQUEST_OVERLAY_PERMISSION_CODE);
        }

        if (!needsOverlayPermission) {
            for (String moduleName : moduleNames) {
                ReactRootView rootView = new ReactRootView(activity);
                rootView.startReactApplication(
                        getReactNativeHost(activity).getReactInstanceManager(),
                        moduleName,
                        launchOptions);
                CACHE.put(moduleName, rootView);
                FLog.i(ReactConstants.TAG, moduleName+" has preload");
            }
        }
    }

    /**
    * 销毁指定的预加载RN模块
    *
    * @param componentName
    */
    public static void 
Android中配置React Native应用JavaScript Bundle通常涉及到以下几个步骤: 1. **设置React Native环境**: 首先确保已安装Node.js、npm以及React Native CLI(`react-native init`)。在命令行中运行`npx react-native init projectName`创建一个新的项目。 2. **构建JavaScript Bundle**: 进入项目目录,执行`cd projectName`,然后使用`npx react-native bundle`命令生成JavaScript Bundle文件。这个文件通常是`.jsbundle`或`.android.bundle`,它包含了应用程序的JavaScript代码及其依赖。 ```bash npx react-native bundle \ --entry-file index.js \ --platform android \ --dev false \ --bundle-output ./assets/index.android.bundle \ --assets-dest ./android/app/src/main/assets/ ``` `-entry-file`指定入口文件,`--platform`指明目标平台(这里是Android),`--dev`如果设为false,会生成生产模式的Bundle,`--bundle-output`指定输出路径,`--assets-dest`则是资源文件夹的目标位置。 3. **添加到AndroidManifest.xml**: 打开`android/app/src/main/AndroidManifest.xml`文件,在`<application>`标签下添加一个 `<meta-data>` 标签,用于引用刚生成的JS Bundle: ```xml <application> ... <meta-data android:name="com.facebook.react ENTRY_POINT_NAME" android:value="@string/react_entry_point_name" /> <!-- 新增 --> <meta-data android:name="android.app.bundled_js_modules" android:value="/assets/index.android.bundle" /> ... </application> ``` 其中`@string/react_entry_point_name`是你项目中对应字符串资源名,告诉React Native从哪里开始执行。 4. **配置gradle**: 在`android/app/build.gradle`文件中,需要添加一些Gradle插件并配置: ```groovy apply plugin: 'com.android.application' ... defaultConfig { ... // 允许混淆 minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' manifestPlaceholders = [manifestApplicationId: applicationId] } ... packagingOptions { pickFirst 'META-INF/**', exclude 'META-INF/*.SF', exclude 'META-INF/*.DSA', exclude 'META-INF/*.RSA' } ``` 5. **运行或打包应用**: 使用`npx react-native run-android`或`cd android && ./gradlew assembleDebug`命令构建并部署到模拟器或设备上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值