美文网首页Android开发Android技术知识Android开发经验谈
[ReactNative]Android原生源码解读(用Mark

[ReactNative]Android原生源码解读(用Mark

作者: meStronger | 来源:发表于2019-06-21 17:38 被阅读9次

    尝试了用Markdown写PPT,阅读效果更佳,欢迎品尝:http://www.vmfor.com/md/2019-01-10ed7ba094-ae05-42c7-a998-8b3d5d31f46c.md

    [slide style="background-image:url('/img/4.jpg')"]

    Android-RN 应用程序

    混合开发

    热更新

    麦文昌 2019-01

    [slide style="background-color:#31456A"]

    前言

    • 原生APP在性能方面具有优势,而ReactNative更加灵活 {:&.fadeIn}
    • 我们将逐渐把APP往原生方面过渡,包括第三方库以及重要的逻辑和界面。
    • Native层提供React原生模块以供React层使用,包括API,UI和后台任务。

    [slide style="background-color:#31456A"]

    目录


    • ReactNative启动流程 {:&.fadeIn}
    • ReactNative混合开发
    • Native模块
    • 热更新
    • 启动优化
    • bundle文件安全
    • 总结

    [slide style="background-color:#31456A"]

    ReactNative启动流程


    {:&.zoomIn}

        AppRegistry.registerComponent('cassecapp', () => cassecapp);
    

    [slide style="background-color:#31456A"]

    ReactNative启动流程

    public class MainApplication extends Application implements ReactApplication {
    
      private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    
        @Override
        protected String getJSBundleFile() {//“index.android.bundle”文件的存储路径
            return CodePush.getJSBundleFile();
        }
    
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }
    
        @Override
        protected List<ReactPackage> getPackages() {
          return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new CodePush(BuildConfig.CODEPUSH_KEY, getApplicationContext(), BuildConfig.DEBUG, "https://codepush.cassmall.com/"),
            ...
          );
        }
      };
    
      @Override
      public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
      }
    
      @Override
      public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
        GrowingIO.startWithConfiguration(this, new Configuration()
            .useID()
            .trackAllFragments()
            .setChannel("测试")
        );
        CrashReport.initCrashReport(getApplicationContext(), "b8b801654b", true);
      }
    }
    
    

    [slide style="background-color:#31456A"]

    ReactNative启动流程


    public class MainActivity extends ReactActivity {
    
        ...
    
        /**
         * Returns the name of the main component registered from JavaScript.
         * This is used to schedule rendering of the component.
         */
        @Override
        protected String getMainComponentName() {
            return "cassecapp";
        }
    
      ...
    }
    

    [slide style="background-color:#31456A"]

    ReactNative启动流程

    package com.facebook.react;
    public abstract class ReactActivity extends Activity
        implements DefaultHardwareBackBtnHandler, PermissionAwareActivity {
    
      private final ReactActivityDelegate mDelegate;
    
      protected ReactActivity() {
        mDelegate = createReactActivityDelegate();
      }
    
      ...
    
      /**
       * Called at construction time, override if you have a custom delegate implementation.
       */
      protected ReactActivityDelegate createReactActivityDelegate() {
        return new ReactActivityDelegate(this, getMainComponentName());
      }
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDelegate.onCreate(savedInstanceState);
      }
    
      @Override
      protected void onPause() {
        super.onPause();
        mDelegate.onPause();
      }
    
      @Override
      protected void onResume() {
        super.onResume();
        mDelegate.onResume();
      }
    
      @Override
      protected void onDestroy() {
        super.onDestroy();
        mDelegate.onDestroy();
      }
    
      @Override
      public void onActivityResult(int requestCode, int resultCode, Intent data) {
        mDelegate.onActivityResult(requestCode, resultCode, data);
      }
    
      @Override
      public boolean onKeyDown(int keyCode, KeyEvent event) {
        return mDelegate.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
      }
      ...
    }
    

    [slide style="background-color:#31456A"]

    ReactNative启动流程

    package com.facebook.react
    /**
     * Delegate class for {@link ReactActivity} and {@link ReactFragmentActivity}. You can subclass this
     * to provide custom implementations for e.g. {@link #getReactNativeHost()}, if your Application
     * class doesn't implement {@link ReactApplication}.
     */
    public class ReactActivityDelegate {
    
      ...
    
      private final @Nullable Activity mActivity;
      private final @Nullable FragmentActivity mFragmentActivity;
      private final @Nullable String mMainComponentName;
    
      private @Nullable ReactRootView mReactRootView;
    
      public ReactActivityDelegate(Activity activity, @Nullable String mainComponentName) {
        mActivity = activity;
        mMainComponentName = mainComponentName;
        mFragmentActivity = null;
      }
    
      protected ReactRootView createRootView() {
        return new ReactRootView(getContext());
      }
    
      protected ReactNativeHost getReactNativeHost() {
        return ((ReactApplication) getPlainActivity().getApplication()).getReactNativeHost();
      }
    
      public ReactInstanceManager getReactInstanceManager() {
        return getReactNativeHost().getReactInstanceManager();
      }
    
      protected void onCreate(Bundle savedInstanceState) {
        if (mMainComponentName != null) {
          loadApp(mMainComponentName);
        }
        mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
      }
    
      protected void loadApp(String appKey) {
        if (mReactRootView != null) {
          throw new IllegalStateException("Cannot loadApp while app is already running.");
        }
        mReactRootView = createRootView();//ReactRootView: 加载React视图的容器
        mReactRootView.startReactApplication(
          //ReactInstanceManager: 负责加载JS,并且管理原生与JS通信
          getReactNativeHost().getReactInstanceManager(),
          appKey,//“cassecapp”
          getLaunchOptions());//加载界面时的一些设置
        getPlainActivity().setContentView(mReactRootView);
      }
    
      ...
    }
    
    

    [slide style="background-color:#31456A"]

    ReactNative启动流程

    package com.facebook.react;
    /**
     * 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;
      }
    
      /**
       * Get the current {@link ReactInstanceManager} instance, or create one.
       */
      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;
      }
    
      protected ReactInstanceManager createReactInstanceManager() {
        ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_START);
        ReactInstanceManagerBuilder builder = ReactInstanceManager.builder()
          .setApplication(mApplication)//必要
          .setJSMainModulePath(getJSMainModuleName())//必要,对应index.js
          .setUseDeveloperSupport(getUseDeveloperSupport()//必要
          .setRedBoxHandler(getRedBoxHandler())
          .setJavaScriptExecutorFactory(getJavaScriptExecutorFactory())
          .setUIImplementationProvider(getUIImplementationProvider())
          .setJSIModulesPackage(getJSIModulePackage())
          .setInitialLifecycleState(LifecycleState.BEFORE_CREATE);//必要,声明加载时机
    
        for (ReactPackage reactPackage : getPackages()) {
          builder.addPackage(reactPackage);//提供给RN交互的原生模块
        }
    
        String jsBundleFile = getJSBundleFile();
        if (jsBundleFile != null) {
          // 外部存储目录下的index.android.bundle文件
          builder.setJSBundleFile(jsBundleFile);
        } else {
          // assets/index.android.bundle
          builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
        }
        ReactInstanceManager reactInstanceManager = builder.build();
        ReactMarker.logMarker(ReactMarkerConstants.BUILD_REACT_INSTANCE_MANAGER_END);
        return reactInstanceManager;
      }
    
    }
    
    

    [slide style="background-color:#31456A"]

    ReactNative启动流程


    {:&.zoomIn}

    ReactRootView {:.highlight}

    ReactInstanceManager {:.highlight}

    [slide style="background-color:#31456A"]

    ReactNative混合开发


    如何在一个在原生界面上显示React组件?

    .

    .

    [slide style="background-color:#31456A"]

    ReactNative混合开发


    {:&.zoomIn}

    import React from 'react';
    import {AppRegistry, StyleSheet, Text, View} from 'react-native';
    
    export default class HelloWorld extends React.Component {
      render() {
        return (
          <View style={styles.container}>
            <Text style={styles.hello}>Hello, World</Text>
          </View>
        );
      }
    }
    
    // .../index.js
    AppRegistry.registerComponent('HelloWorld', () => HelloWorld);
    AppRegistry.registerComponent('RNOnLayout', () => RNOnLayout);
    AppRegistry.registerComponent('ExternalBundle', () => ExternalBundle);
    

    [slide style="background-color:#31456A"]

    ReactNative混合开发

    public class HelloWorldActivity extends Activity {
    
        private ReactInstanceManager mReactInstanceManager;
        private ReactRootView mReactRootView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            mReactRootView = new ReactRootView(this);
            mReactInstanceManager = ReactInstanceManager.builder()
                    .setApplication(getApplication())
                    .setBundleAssetName("index.android.bundle")//assets 文件目录下的bundle文件
                    .setJSMainModulePath("index")//对应index.js
                    .addPackage(new MainReactPackage())
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();
            //  "HelloWorld" 对应index.js中的:
            // AppRegistry.registerComponent('HelloWorld', () => HelloWorld);
            mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null);
    
            setContentView(mReactRootView);
        }
    }
    

    [slide style="width:400"]

    ReactNative混合开发

    .

    .

    [slide style="background-color:#31456A"]

    ReactNative混合开发

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="#f2f2f2"
            android:gravity="center"
            android:text="这里是原生部分"
            android:textColor="#000000" />
    
        <com.facebook.react.ReactRootView
            android:id="@+id/react_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
    

    [slide style="background-color:#31456A"]

    ReactNative混合开发

    public class NativeReactActivity extends BaseReactActivity {
    
        private ReactInstanceManager mReactInstanceManager;
        private ReactRootView mReactRootView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_react_test);
            //找到布局中的ReactRootView
            mReactRootView = findViewById(R.id.react_view);
            mReactInstanceManager = ReactInstanceManager.builder()
                    .setApplication(getApplication())
                    .setBundleAssetName("index.android.bundle") //assets 文件目录下的bundle文件
                    .setJSMainModulePath("index")  //对应index.js
                    .addPackage(new MainReactPackage())
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();
            mReactRootView.startReactApplication(mReactInstanceManager, "RNOnLayout", null);
        }
    }
    
    

    [slide style="background-color:#31456A"]

    ReactNative混合开发

    .

    .

    [slide style="background-color:#31456A"]

    ReactNative混合开发

    public class ExternalReactActivity extends BaseReactActivity {
    
        private ReactInstanceManager mReactInstanceManager;
        private ReactRootView mReactRootView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_react_test);
            //找到布局中的ReactRootView
            mReactRootView = findViewById(R.id.react_view);
            //获取bundle文件路径:在外部存储空间"test"文件夹下
            String path = Environment.getExternalStorageDirectory() + "/test/index.android.bundle";
            //初始化ReactInstanceManager
            mReactInstanceManager = ReactInstanceManager.builder()
                    .setApplication(getApplication())
                    // .setBundleAssetName("index.android.bundle")
                    .setJSMainModulePath("index") //对应index.js
                    .addPackage(new MainReactPackage())//原生模块
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setJSBundleFile(path) //设置文件路径
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();
    
            //"ExternalBundle" 对应js中 :AppRegistry.registerComponent('ExternalBundle', () => ExternalBundle);
            mReactRootView.startReactApplication(mReactInstanceManager, "ExternalBundle", null);
        }
    }
    

    [slide style="background-color:#31456A"]

    ReactNative混合开发

    .

    .

    [slide style="background-color:#31456A"]

    Native原生模块

    .

    .

    [slide style="background-color:#31456A"]

    Native原生模块(UI)

    /**
    * 1.创建一个ViewManager类
    * 例子: 实现一个图片显示器
    */
    public class RCTImageManager extends SimpleViewManager<RCImageView> {
    
        private static final String RC_IMAGE_VIEW = "RCImageView";
    
         /**
         * 2. 实现getName方法,返回该组件的名字
         */
        @Override
        public String getName() {
            return RC_IMAGE_VIEW;
        }
    
        /**
         * 3. 实现createViewInstance方法,创建视图,并初始化为默认的状态
         */
        @Override
        protected RCImageView createViewInstance(ThemedReactContext reactContext) {
            return new RCImageView(reactContext, Fresco.newDraweeControllerBuilder(), null, null);
        }
    
      /*
      * 4. 通过@ReactProp(或@ReactPropGroup)注解来导出属性的设置方法。
      */
    
        //url属性 src = {'https://www.baidu.com/img/bd_logo1.png'}
        @ReactProp(name = "src")
        public void setSrc(ReactImageView view, @Nullable String sources) {
            WritableMap map = Arguments.createMap();
            map.putString("uri", sources);
            WritableArray array = Arguments.createArray();
            array.pushMap(map);
            //转换成ReadableArray传给View
            view.setSource(array);
        }
    
        @ReactProp(name = "borderRadius", defaultFloat = 0f)
        public void setBorderRadius(ReactImageView view, float borderRadius) {
            view.setBorderRadius(borderRadius);
        }
    
        @ReactProp(name = ViewProps.RESIZE_MODE)
        public void setResizeMode(ReactImageView view, @Nullable String resizeMode) {
            view.setScaleType(ImageResizeMode.toScaleType(resizeMode));
        }
    
        /**
         * 注册回调事件
         */
        @javax.annotation.Nullable
        @Override
        public Map<String, Object> getExportedCustomBubblingEventTypeConstants() {
            return MapBuilder.<String, Object>builder()
                    //把topChange注册到系统中
                    .put("topChange",
                            MapBuilder.of(
                                    "phasedRegistrationNames",
                                    MapBuilder.of("bubbled", "onChange")))//onChange是暴露给 R 层的接口
                    .build();
        }
    
    }
    
    

    [slide style="background-color:#31456A"]

    Native原生模块(UI)

    参数对照表

    |Java | JavaScript|
    :-------|:-------|:------
    布尔型|Boolean | Bool
    整形|Integer | Number
    双精度浮点型|Double | Number
    浮点型|Float | Number
    字符串|String | String
    回调|Callback | function
    映射|ReadableMap | Object
    数组|ReadableArray | Array

    [slide style="background-color:#31456A"]

    Native原生模块(UI)

    @Override
    public class NativePackage implements ReactPackage {
        /**
         * 5.在ReactPackage中注册ViewManager
         */
        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            return Arrays.<ViewManager>asList(
                    new RCTImageManager() //原生图片显示UI
            );
        }
    }
    

    [slide style="background-color:#31456A"]

    Native原生模块(UI)

    //6.实现对应的JavaScript模块
    class NativeUIExample extends Component {
    
      static navigationOptions = {
        title: 'NativeUIExample',
      };
    
      _onButtonPress(){
          alert("onButtonPress");
      }
    
      render() {
        return (
          <View style={styles.container}>
            <RCImageView
              src = {'http://www.casstime.com/images/Product2.jpg'}
              borderRadius= {25}
              style={{width: 300, height: 225}}
              onChangeMessage = {this._onButtonPress}
            />
          </View>
        );
      }
      ...
    }
    
    

    [slide style="background-color:#31456A"]

    Native原生模块(UI)

    .

    .

    [slide style="background-color:#31456A"]

    Native原生模块(API)

    原生模块给React层提的供API:

    • 原生的第三方库API {:&.fadeIn}
    • 可复用的原生代码
    • 高性能的、多线程的原生代码、譬如图片处理、数据库、或者各种高级扩展等等

    [slide style="background-color:#31456A"]

    Native原生模块(API)

    /*
    * 1. 创建一个新的Java类继承ReactContextBaseJavaModule,并命名为ToastModule.java
    * 例子: 实现一个吐司模块
    */
    public class ToastModule extends ReactContextBaseJavaModule {
    
      private static final String TOAST_MODULE = "ToastExample";
    
        private static final String DURATION_SHORT_KEY = "SHORT";
        private static final String DURATION_LONG_KEY = "LONG";
    
        public ToastModule(ReactApplicationContext reactContext) {
            super(reactContext);
        }
    
        //2. 实现getName方法,返回该模块的名字
        @Override
        public String getName() {
            return TOAST_MODULE;
        }
    
        //3. 实现getConstants方法,返回需要导出给JavaScript使用的常量
        @Nullable
        @Override
        public Map<String, Object> getConstants() {
            Map<String, Object> constants = new HashMap<>();
            constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
            constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
            return constants;
        }
    
        //4. 使用注解@ReactMethod导出一个方法给JavaScript使用
        @ReactMethod(isBlockingSynchronousMethod = false)
        public void show(String message, int duration) {
            Toast.makeText(getReactApplicationContext(), message, duration).show();
        }
    }
    
    

    [slide style="background-color:#31456A"]

    Native原生模块(API)

    public class NativePackage implements ReactPackage {
    
        /**
         * 5.在ReactPackage中注册ToastModule模块
         */
        @Override
        public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
            return Arrays.<NativeModule>asList(
                    new ToastModule(reactContext),//吐司模块
        }
    }
    

    [slide style="background-color:#31456A"]

    Native原生模块(API)


    {:&.fadeIn}

    // ToastExample.js
    // 通常我们都会把原生模块封装成一个 JavaScript 模块
    import { NativeModules } from "react-native";
    
    module.exports = NativeModules.ToastExample;
    
    // 在JavaScript代码中可以这样调用:
    import ToastExample from "./ToastExample";
    
    ToastExample.show("Awesome", ToastExample.SHORT);
    

    [slide style="background-color:#31456A"]

    Native原生模块(API)

    其他特性

    • 回调函数:com.facebook.react.bridge.Callback
    • Promises: 原生模块还可以使用Promise来简化代码
    • 事件发射器:RCTDeviceEventEmitter
    • 生命周期监听:ActivityEventListener&LifecycleEventListener

    [slide style="background-color:#31456A"]

    Native原生模块(Task)

    /*
    * 1.创建一个类继承HeadlessJsTaskService
    * 例子: 模拟网络状态监听
    */
    public class OnNetworkChangeTaskService extends HeadlessJsTaskService {
    
        /**
         * 2.配置任务
         */
        @Nullable
        @Override
        protected HeadlessJsTaskConfig getTaskConfig(Intent intent) {
            if (intent==null)return null;
            Bundle extras = intent.getExtras();
            if (extras == null) return  null;
            HeadlessJsTaskConfig taskConfig = new HeadlessJsTaskConfig(
                    "NetworkChangeTask", //任务名称
                    Arguments.fromBundle(extras), // 任务参数
                    5000, //任务超时时间
                    true // 是否允许在前台运行,默认false
            );
            return taskConfig;
        }
    }
    
    

    [slide style="background-color:#31456A"]

    Native原生模块(Task)

    /*
    * 3.在APP切换到后台的时候开启后台任务监听网络状态,
    * 并且在网络发生改变时执行JavaScript任务;
    */
    
    Intent serviceIntent = new Intent(context, OnNetworkChangeTaskService.class);
    serviceIntent.putExtra("hasInternet", hasInternet);
    context.startService(serviceIntent);
    
    

    [slide style="background-color:#31456A"]

    Native原生模块(Task)

    // 5. 创建执行任务的NetworkChangeTask.js文件
    module.exports = async (taskData) => {
        if (taskData["hasInternet"]) {
            console.log('网络可用')
        }else{
            console.log('网络不可用')
        }
    };
    
    /*
    *5.在index.js中引用创建执行任务的NetworkChangeTask.js文件;
    *  并注册`NetworkChangeTask`任务
    */
    import NetworkChangeTask from './NetworkChangeTask';
    
    AppRegistry.registerHeadlessTask("NetworkChangeTask", () => require("NetworkChangeTask"));
    

    [slide style="background-color:#31456A"]

    Native原生模块(Task)

    module.exports = async (taskData) => {
        if (taskData["hasInternet"]) {
            console.log('网络可用')
        }else{
            console.log('网络不可用')
        }
    };
    

    [slide style="background-color:#31456A"]

    热更新

    ReactNative热更新原理:

    1. 版本更新时,从服务器重新拉取bundle文件和图片资源到本地; {:&.fadeIn}
    2. 在setJSBundleFile()方法中返回新的bundle文件路径;
    3. ReactInstanceManager加载新的bundle文件。

    [slide style="background-color:#31456A"]

    热更新 第三方库

    react-native-pushy

    ReactNative中文网推出的代码热更新服务:

    1. 每个应用每个月不超过10000次下载; {:&.fadeIn}
    2. 基于bsdiff算法创建的超小更新包,通常版本迭代后在1-10KB之间,避免数百KB的流量消耗;
    3. 支持崩溃回滚,安全可靠;
    4. 开放API,提供更高扩展性;
    5. 跨越多个版本进行更新时,只需要下载一个更新包,不需要逐版本依次更新。

    [slide style="background-color:#31456A"]

    热更新 第三方库

    react-native-code-push

    微软推出的代码热更新服务:

    1. 支持版本回滚; {:&.fadeIn}
    2. 支持图片增量更新;
    3. 官方服务器在国外,国内访问受限,建议自建服务;
    4. 没有开放后台源码。

    [slide style="background-color:#31456A"]

    热更新

    搭建自己的热更新服务

    1. 打包bundle文件和图片文件,并上传服务器; {:&.fadeIn}
    2. 使用bsdiff对比两个版本的bundle文件得到补丁文件;
    3. 检查更新,下载补丁文件和图片;
    4. 使用bspatch对文件打补丁;
    5. 增量更新bundle文件和图片文件(Bsdiff工具);
    6. ReactInstanceManager空闲时重新加载bundle文件(或重启app时生效)。

    [slide style="background-color:#31456A"]

    启动优化

    jsBundle文件预加载

    1. ReactRootView.startReactApplication() {:&.fadeIn}
    2. ReactInstanceManager.recreateReactContextInBackground()
    3. ReactInstanceManager.runCreateReactContextOnNewThread()
    public void startReactApplication(
          ReactInstanceManager reactInstanceManager,
          String moduleName,
          @Nullable Bundle initialProperties) {
        Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "startReactApplication");
        try {
          ...
          if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
          //后台创建ReactContext(加载jsBundle)
            mReactInstanceManager.createReactContextInBackground();
          }
          attachToReactInstanceManager();
        } finally {
          Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
        }
      }
    
    

    [slide style="background-color:#31456A"]

    启动优化

    jsBundle文件预加载

    private void runCreateReactContextOnNewThread(final ReactContextInitParams initParams) {
        ...
      //开启子线程
        mCreateReactContextThread =
            new Thread((Runnable)()-> {
                    ...
                    try {
                      Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
                      final ReactApplicationContext reactApplicationContext =
                          createReactContext(
                              //加载jsBundle
                              initParams.getJsExecutorFactory().create(),
                              initParams.getJsBundleLoader());
                      ...
    
                      Runnable setupReactContextRunnable = new Runnable() {()->{
                          ...
                          //在主线程设置ReactRootView
                          setupReactContext(reactApplicationContext);
                          ...
                      }};
                      reactApplicationContext.runOnNativeModulesQueueThread(setupReactContextRunnable);
                      UiThreadUtil.runOnUiThread(maybeRecreateReactContextRunnable);
                    } catch (Exception e) {
                      mDevSupportManager.handleException(e);
                    }
                  }
                });
        ReactMarker.logMarker(REACT_CONTEXT_THREAD_START);
        mCreateReactContextThread.start();
    }
    
    

    [slide style="background-color:#31456A"]

    启动优化

    • 全局单例的ReactInstanceManager {:&.fadeIn}
    • ReactInstanceManager的创建时机

    [slide style="background-color:#31456A"]

    启动优化

    • 预加载ReactRootView {:&.fadeIn}
    • 缓存并复用ReactRootView

    [slide style="background-color:#31456A"]

    bundle文件安全

    裸奔的jsBundle

    1. 网络接口安全。 {:&.fadeIn}

    2. jsBundle防篡改。为防止篡改js入侵app业务,需对jsBundle做签名校验,
      一是下载文件后校验其完整性,二是每次加载jsBundle时校验。

    3. jsBundle业务安全。因为jsBundle是明文,所以业务中需要进行加解密等
      敏感措施就不能在js层实现,应该在native层实现加解密暴露给js接口调用。

    [slide style="background-color:#31456A"]

    总结

    • ReactNative启动流程 {:&.fadeIn}
    • ReactNative混合开发
    • Native模块
    • 热更新
    • 启动优化
    • bundle文件安全

    [slide style="background-color:#31456A"]


    End

    「Talk is cheap. Show me the code」

    相关文章

      网友评论

        本文标题:[ReactNative]Android原生源码解读(用Mark

        本文链接:https://www.haomeiwen.com/subject/mhaarqtx.html