React native热更新思路(一)之ReactNativeHost类解析【适用于Android开发者】
来源:互联网 发布:js 上传照片插件 编辑:程序博客网 时间:2024/06/06 20:35
React Native发展到今天,之所以受到大家的青睐一个最重要的原因就是它支持动态更新,并且这种动态更新的方式较原生的来看要方便的很多。所以今天我将带领大家来看看React native是如何实现动态更新的。
首先我们一起来看看ReactNativeHost类到底写了些什么?
/** * Simple class that holds an instance of {@link ReactInstanceManager}. This can be used in your * {@link Application class} (see {@link ReactApplication}), or as a static field. */public abstract class ReactNativeHost { private final Application mApplication; private @Nullable ReactInstanceManager mReactInstanceManager; protected ReactNativeHost(Application application) { mApplication = application; } /** * 获取一个react native的核心管理类的的对象 */ public ReactInstanceManager getReactInstanceManager() { if (mReactInstanceManager == null) { mReactInstanceManager = createReactInstanceManager(); } return mReactInstanceManager; } /** * Get whether this holder contains a {@link ReactInstanceManager} instance, or not. I.e. if * {@link #getReactInstanceManager()} has been called at least once since this object was created * or {@link #clear()} was called. */ public boolean hasInstance() { return mReactInstanceManager != null; } /** * Destroy the current instance and release the internal reference to it, allowing it to be GCed. */ public void clear() { if (mReactInstanceManager != null) { mReactInstanceManager.destroy(); mReactInstanceManager = null; } }/** * 构建 ReactInstanceManager 对象,ReactInstanceManager会在下次详细介绍 */protected ReactInstanceManager createReactInstanceManager() { ReactInstanceManager.Builder builder = ReactInstanceManager.builder() .setApplication(mApplication) .setJSMainModuleName(getJSMainModuleName()) .setUseDeveloperSupport(getUseDeveloperSupport()) .setRedBoxHandler(getRedBoxHandler()) .setUIImplementationProvider(getUIImplementationProvider()) .setInitialLifecycleState(LifecycleState.BEFORE_CREATE); for (ReactPackage reactPackage : getPackages()) { builder.addPackage(reactPackage); }/** * 今天的重点,判断是否存在jsbundle,如果存在则加载,反之则加载assets中的jsbundle* 这里是热更新的开始 具体如何判断请看getJSBundleFile方法 */String jsBundleFile = getJSBundleFile(); if (jsBundleFile != null) { builder.setJSBundleFile(jsBundleFile); } else { builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName())); } return builder.build(); } /** * Get the {@link RedBoxHandler} to send RedBox-related callbacks to. */ protected @Nullable RedBoxHandler getRedBoxHandler() { return null; } protected final Application getApplication() { return mApplication; } /** * Get the {@link UIImplementationProvider} to use. Override this method if you want to use a * custom UI implementation. * * Note: this is very advanced functionality, in 99% of cases you don't need to override this. */ protected UIImplementationProvider getUIImplementationProvider() { return new UIImplementationProvider(); } /** * Returns the name of the main module. Determines the URL used to fetch the JS bundle * from the packager server. It is only used when dev support is enabled. * This is the first file to be executed once the {@link ReactInstanceManager} is created. * e.g. "index.android" */ protected String getJSMainModuleName() { return "index.android"; } /** * 这里可以设置你的最新jsbundle进来 */ protected @Nullable String getJSBundleFile() { return null; } /** * Returns the name of the bundle in assets. If this is null, and no file path is specified for * the bundle, the app will only work with {@code getUseDeveloperSupport} enabled and will * always try to load the JS bundle from the packager server. * e.g. "index.android.bundle" */ protected @Nullable String getBundleAssetName() { return "index.android.bundle"; } /** * Returns whether dev mode should be enabled. This enables e.g. the dev menu. */ protected abstract boolean getUseDeveloperSupport(); /** * Returns a list of {@link ReactPackage} used by the app. * You'll most likely want to return at least the {@code MainReactPackage}. * If your app uses additional views or modules besides the default ones, * you'll want to include more packages here. */ protected abstract List<ReactPackage> getPackages();}
代码中有关热更新的地方我都用红色字体做了中文注释
看完ReactNativeHost类的代码,我们大致可以了解到React native的确为我们提供了热更新的功能,并且我们只需要实现ReactNativeHost类的同时去重写两个方法即可,如下
protected @Nullable String getJSBundleFile() { return null;}
protected String getJSMainModuleName() { return "index.android";}
最新版的React native为我们提供了一个ReactApplication,我们只需要继承它去实现getReactNativeHost方法就可以将我们的重写好的ReactNativeHost配置进去,这样就初步搭建好了React native的热更新
下面我们一起来找找这里面的坑
1.这里没有具体介绍jsbundle的校验问题,每个人的校验方式都不同,也有很多方式,不懂得可以百度
2.有人可能会疑惑,ReactNativeHost是在Application中配置好的,如果说程序运行过程中有新的jsbundle下载到本地,那我应该如何去加载它呢?
作者一开始也想着手动去调用一下加载的方法,可是怎么都没找到,后来看了codepush源码之后,发现他们利用类反射去调用了一个叫recreateReactContextInBackground的方法,后来又去查看这个方法的源码才明白这样是完全可行的【切记在UI thread 中去调用它】
/** * Recreate the react application and context. This should be called if configuration has * changed or the developer has requested the app to be reloaded. It should only be called after * an initial call to createReactContextInBackground. * * Called from UI thread. */public void recreateReactContextInBackground() { Assertions.assertCondition( mHasStartedCreatingInitialContext, "recreateReactContextInBackground should only be called after the initial " + "createReactContextInBackground call."); recreateReactContextInBackgroundInner();}3.资源文件该怎么办呢?
其实React native已经为我们提供好了资源文件的加载,我们只需要将最新的资源文件和你的jsbundle保存在相同的路径下即可,具体的实现大家可以看React native image加载本地图片的实现源码。
4.是否有源码可以分享出来?
前段时间写了一个,只是将热更新的流程走通了,还有一些功能要逐步完善,有兴趣的可以一起GitHub
今天大致带大家了解了下ReactNativeHost到底做了哪些事,对于初学RN的伙伴来说,利用今天分享完全可以体验到React native的热更新功能。
希望对大家有帮助
QQ群581621024
- React native热更新思路(一)之ReactNativeHost类解析【适用于Android开发者】
- React-Native 热更新尝试(Android)
- React-Native 热更新尝试(Android)
- react-native 热更新(android)
- 深度解析Gradle编译React native时遇到的那些坑【适用于Android开发者】
- [深入剖析React Native]热更新之react-native-pushy使用指南(Android)
- React-native 热更新之pushy!
- react-native热更新之codepush使用
- React native 热更新之CodePushy
- android中react-native热更新
- react native热更新
- React Native热更新
- Android React Native 热更新 自己搭建热更新平台
- React Native 热更新实现
- React Native-Pushy热更新
- React Native热更新方案
- React-Native 热更新 CodePush
- Unity3d热更新(一):更新思路
- 周总结2016.12-18
- 恶意爬虫这样窥探、爬取、威胁你的网站
- SQL SERVER日常运维巡检系列之七——日志
- 魅族Flyme5.x系统INSTALL_FAILED_SHARED_USER_INCOMPATIBLE
- Burst Balloons——Difficulty:Hard
- React native热更新思路(一)之ReactNativeHost类解析【适用于Android开发者】
- Python 的特点
- HoverMenu
- SQL SERVER日常运维巡检系列之八——性能
- Unix域套接字
- Android线程通信,Handler+Looper+Message机制解析
- Spring Boot 添加Log4j框架
- android进程间通讯aidl demo
- Linux下安装Tomcat