React Native 升级策略 简述

来源:互联网 发布:sql数据库设置 编辑:程序博客网 时间:2024/05/17 08:57

debug模式下

React Native以热更新而出名,而它的热更新在开发阶段,通过调试菜单,可以实现reload hot load等,也就是你可以手动点reload 也可以选择 hot load 这两者的区别是什么呢
reload 你点击一次,会执行

getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();

这个代码.就是会重新加载JSBundle.js文件,然后更新整个应用.

而hot load 这个东西可以记载场景,也就是说当你修改了你的代码,保存之后,在你调试的设备上直接就会变成你修改代码,不需要重新刷新.而这种更新方式其实是我们最需要的.
目前,本人暂时还没有找到这种方式的最佳实现形式,Facebook没有提供release方式的,如果通过阅读RN源码是可以找到解决方案的.
而reload这种更新方式,是可以通过修改RN源码,也就是打包进你的apk的不是Facebook官方出的包,是我们修改过得,是可以满足的.


release模式下

在release模式下实现RN的升级,其实就是生产环境了.
下面,先说说生产环境如何更新JSBundle文件.
Facebook提供了一个方法,这个方法就是我们可升级JSBundle文件的路径,只要我们改了路径,然后该路径下有这个文件,然后下次我们重启这个应用的时候,就会自动加载这个最新的JSBundle文件.

      protected String getJSBundleFile() {            super.getJSBundleFile();        }

如果你这么写的话,默认打包的APK,就会从你的assert目录下,去找这个文件.
但是这个目录在安装了apk以后就不可更改了.

(1) 被动升级策略

所以要做的事,就是改了这个路径,比如下面的:

      protected String getJSBundleFile() {            String jsBundleFile = getFilesDir().getAbsolutePath() + "/index.android.bundle";            File file = new File(jsBundleFile);            return file != null && file.exists() ? jsBundleFile : null;        }

如果我们外面的目录里,有这个文件,就使用我们最新的,否则返回空,就是使用默认的assert目录下的.
这个外在的目录,你可以随便设置的,只要在设备下能读写的文件内即可.
如果你只有这种需求的话,那你就做一个服务端,然后客户端定期去请求是否有版本更新,如果检测到版本号更新,就去下载解压到对应的文件夹位置.当应用下次启动的时候,就会自动使用最新的.

(2) 主动升级策略

所谓的主动升级策略,就是我可以控制什么时候更新,无须下次启动应用的时候去默认升级.因为有些应用是不会退出的,比如QQ 微信,这些应用你基本上从来不会从手机端退出,或者TV端的一些内置应用,从不退出,除非手机重启了,要不升级还是存在弊端.
这种情况下,我们最好就主动升级一下.
这种应用场景虽然不多,但是还是用的到的.
这种场景下,就需要我们去看看debug模式下,Facebook是怎么做的,修改其RN源码,编译后,再打包到自己的apk内.
其实就是让

getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();

这句代码生效即可.因为默认的RN源码,在release模式下,你就算调用了这句代码也是不生效的,只有在debug模式下,才是生效的.这个就看Facebook,是怎么考虑的了,或者认为还不成熟.
这个修改应该不难,本人没改,只是看了一下源码,觉得不难.
网上看到有人使用反射的方法调用函数,即可调用reload,因为这个方法是private,私有的.

  private void recreateReactContextInBackground(      JavaScriptExecutor.Factory jsExecutorFactory,      JSBundleLoader jsBundleLoader) {    UiThreadUtil.assertOnUiThread();    ReactContextInitParams initParams =        new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);    if (mReactContextInitAsyncTask == null) {      // No background task to create react context is currently running, create and execute one.      mReactContextInitAsyncTask = new ReactContextInitAsyncTask();      mReactContextInitAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, initParams);    } else {      // Background task is currently running, queue up most recent init params to recreate context      // once task completes.      mPendingReactContextInitParams = initParams;    }  }

仅供参考.

(3) 最牛逼的升级策略

在debug模式下,完整的名称叫Enable Hot Reloading 这种方式有多牛逼,每次会自动生成增量包,然后加载,然后在保存当前状态的情况下,更新的最新代码.
就是用户完全感觉不到的情况下,你已经升级了最新的apk.这是不是很牛逼.

那么这种策略,要如何去做呢,我也很想搞定,但是只有开发模式有,release模式没有.后续尝试一下,改改RN源码,看好用不好用.

(4) 升级中关键问题

RN虽然说是热更新,但是随着应用的不断增大,Bundle文件也是在不停的增加,如果是电商的项目,还会有很多的文件.如果你在一种用户不在乎流量的场景下,那么你的升级完全不需要关心下载大小的问题.可以忽略.
如果是手机端应用,用户的流量还是要花钱的,不过你可以检测,在WiFi的情况下自动下载.
如果想随时下载,就需要用到补丁方案,这个方案目前apk中用的也比较多,不需要全面升级,只需要对比出不同,生成补丁包即可.具体的实施,本人也是还在研究中.

0 0