做了2年React Native,之前也看过一些Android 方面的文章,自己也都只是看了个大概,也就是一知半解,现在想着自己看一遍,好提升一下自己。 我文笔不怎么好,这个主要是用于自己学习记录的。
我们都知道一个RN项目创建出来的时候Android 原生会有2个文件 一个MainActivity,一个MainApplication。现在我们来看看MainApplication做的什么东西。
MainApplication
public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List<ReactPackage> getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List<ReactPackage> packages = new PackageList(this).getPackages(); // Packages that cannot be autolinked yet can be added manually here, for example: // packages.add(new MyReactNativePackage()); return packages; } @Override protected String getJSMainModuleName() { return "index"; } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); } }
这个Application 会 实现一个接口 ReactApplication
public interface ReactApplication { /** * Get the default {@link ReactNativeHost} for this app. */ ReactNativeHost getReactNativeHost(); }
这个接口值生命了一个方法,很简单。
然后我们在去看MainApplication 里面实现了getReactNativeHost 这个方法 返回了在MainApplication中生命的 ReactNativeHost(mReactNativeHost)
ReactNativeHost
public abstract class ReactNativeHost { private final Application mApplication; // Application上下文对象 private @Nullable ReactInstanceManager mReactInstanceManager; // ReactInstanceManager实例 protected ReactNativeHost(Application application) { mApplication = application; // 实例化的时候将 application 传入并持有 } /** *获得当前的ReactInstanceManager, 如果没有则进行创建 */ public ReactInstanceManager getReactInstanceManager() { if (mReactInstanceManager == null) { ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_START); mReactInstanceManager = createReactInstanceManager(); ReactMarker.logMarker(ReactMarkerConstants.GET_REACT_INSTANCE_MANAGER_END); } return mReactInstanceManager; } /** * 判断当前的ReactNativeHost是否持用ReactInstanceManager实例 */ public boolean hasInstance() { return mReactInstanceManager != null; } /** * 销毁当前持有的ReactInstanceManager实例 */ public void clear() { if (mReactInstanceManager != null) { mReactInstanceManager.destroy(); mReactInstanceManager = null; } } protected ReactInstanceManager createReactInstanceManager() { ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START); // 通过Builder设计模式,来构建ReactInstanceManager实例 ReactInstanceManagerBuilder builder = ReactInstanceManager.builder() .setApplication(mApplication) .setJSMainModulePath(getJSMainModuleName()) .setUseDeveloperSupport(getUseDeveloperSupport()) .setRedBoxHandler(getRedBoxHandler()) .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory()) .setUIImplementationProvider(getUIImplementationProvider()) .setJSIModulesPackage(getJSIModulePackage()) .setInitialLifecycleState(LifecycleState.BEFORE_CREATE); // 将 getPackages 中注册的ReactPackage 都注册到 ReactInstanceManager 中 for (ReactPackage reactPackage : getPackages()) { builder.addPackage(reactPackage); } // 这个方法是用于 如果你的jsbundle 不是放在assets中的时候可以指定bundle加载的路径 String jsBundleFile = getJSBundleFile(); if (jsBundleFile != null) { builder.setJSBundleFile(jsBundleFile); } else { // Assertions.assertNotNull(getBundleAssetName()) 这个方法仅仅只是判断 getBundleAssetName() 的 返回结果是否为null builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName())); } ReactInstanceManager reactInstanceManager = builder.build(); ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_END); return reactInstanceManager; // 返回 ReactInstanceManager 实例 } /** * Get the {@link RedBoxHandler} to send RedBox-related callbacks to. */ protected @Nullable RedBoxHandler getRedBoxHandler() { return null; } /** * Get the {@link JavaScriptExecutorFactory}. Override this to use a custom * Executor. */ protected @Nullable JavaScriptExecutorFactory getJavaScriptExecutorFactory() { 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(); } protected @Nullable JSIModulePackage getJSIModulePackage() { return null; } /** * 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"; } /** * Returns a custom path of the bundle file. This is used in cases the bundle should be loaded * from a custom path. By default it is loaded from Android assets, from a path specified * by {@link getBundleAssetName}. * e.g. "file://sdcard/myapp_cache/index.android.bundle" */ 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. */ public 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(); }