美文网首页
React Native 初探

React Native 初探

作者: 詹徐照 | 来源:发表于2018-10-07 17:22 被阅读26次

    React Native是啥?

    是一款用JavaScriptScript编写原生(Android,iOS)应用的框架。

    原理是啥?

    总体来看,整套React Native框架分为三层,如下图所示:


    image.png
    • Java层:该层主要提供了Android的UI渲染器UIManager(将JavaScript映射成Android Widget)以及一些其他的功能组件(例如:Fresco、Okhttp)等。
    • C++层:该层主要完成了Java与JavaScript的通信以及执行JavaScript代码两件工作。JSCore,即JavaScriptCore,JS解析的核心部分,IOS使用的是内置的JavaScriptCore,Androis上使用的是 https://webkit.org 家的jsc.so
    • JavaScript层:该层提供了各种供开发者使用的组件以及一些工具库。

    通讯机制

    关于整个RN的通信机制,可以用一句话来概括:

    JNI作为C++与Java的桥梁,JSC作为C++与JavaScript的桥梁,而C++最终连接了Java与JavaScript。
    RN应用通信桥结构图如下所示:

    image
    Java 调用 JS
    image
    JS 调用 Java
    image

    启动流程

    image

    JavaScript层组件渲染

    image

    从上图我们可以很容易看出,Java层的组件渲染分为以下几步:

    1. JS层通过C++层把创建View的请求发送给Java层的UIManagerModule。
    2. UIManagerModule通过UIImplentation对操作请求进行包装。
    3. 包装后的操作请求被发送到View处理队列UIViewOperationQueue队列中等待处理。
    4. 实际处理View时,根据class name查询对应的ViewNManager,然后调用原生View的方法对View进行相应的操作。

    用RN写APP是怎样的一种体验

    Hello World快速体验

    下载安装Node,依次执行(读条)下面几行代码

    npm install -g create-react-native-app
    create-react-native-app AwesomeProject
    cd AwesomeProject
    npm start
    

    顺利执行完后显示如下结果,


    image

    根据提示可以通过扫码在手机上看到代码运行效果
    项目目录结构

    image
    React Native使用JSX写项目的。
    JSX is a syntax extension to JavaScript.
    Introducing JSX

    Basic

    Hello World


    image

    布局


    image
    列表
    image

    网络请求


    网络请求

    自定义控件

    image

    RN Android混合开发

    环境版本
    react-native-cli: 2.0.1
    react-native: 0.57.1

    项目初始化

    choco install -y nodejs.install python2 jdk8
    npm install -g react-native-cli
    1. Install Android Studio
    2. Install the Android SDK
    3. Configure the ANDROID_HOME environment variable
    Preparing the Android device
    react-native init AwesomeProject
    cd AwesomeProject
    react-native run-android
    

    从Android主入口到JS主入口

    JS 工程目录结构


    image

    JS 工程中的Android 工程结构
    MainApplication.java


    image
    MainActivity.java
    image

    ReactActivity.java


    image
    ReactActivityDelegate.java
    image
    ReactNativeHost.java
    ReactNativeHost-structure
    image
    ReactNativeHost-createReactInstanceManager
    image
    ReactNativeHost-getMainModuleName
    image

    index.js


    image
    App.js
    image

    Android的 生命周期事件 是如何分发到 JS的世界 中的

    ReactActivityDelegate


    image

    ReactInstanceManager


    image
    image
    ReactContext
    image

    LifecycleEventListener


    image

    Android 调 RN

    1. Java 发送事件

    RCTDeviceEventEmitter.java

    ...
    private void sendEvent(ReactContext reactContext,
                           String eventName,
                           @Nullable WritableMap params) {
      reactContext
          .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
          .emit(eventName, params);
    }
    ...
    WritableMap params = Arguments.createMap();
    ...
    sendEvent(reactContext, "keyboardWillShow", params);
    

    2. JavaScript 接受事件

    import { DeviceEventEmitter } from 'react-native';
    ...
    
    var ScrollResponderMixin = {
      mixins: [Subscribable.Mixin],
    
    
      componentWillMount: function() {
        ...
        this.addListenerOn(DeviceEventEmitter,
                           'keyboardWillShow',
                           this.scrollResponderKeyboardWillShow);
        ...
      },
      scrollResponderKeyboardWillShow:function(e: Event) {
        this.keyboardWillOpenTo = e;
        this.props.onKeyboardWillShow && this.props.onKeyboardWillShow(e);
      },
    

    RN 调 Android

    1. 声明JavaModule

    • extends ReactContextBaseJavaModule
    • getName()
    • @ReactMethod
    public class ToastModule extends ReactContextBaseJavaModule {
    
      private static final String DURATION_SHORT_KEY = "SHORT";
      private static final String DURATION_LONG_KEY = "LONG";
    
      public ToastModule(ReactApplicationContext reactContext) {
        super(reactContext);
      }
      
      @Override
      public String getName() {
        return "ToastExample";
      }
      
      @ReactMethod
      public void show(String message, int duration) {
        Toast.makeText(getReactApplicationContext(), message, duration).show();
      }
    }
    

    2. 注册JavaModule

    CustomToastPackage.java

    public class CustomToastPackage implements ReactPackage {
    
      @Override
      public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
      }
    
      @Override
      public List<NativeModule> createNativeModules(
                                  ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
    
        modules.add(new ToastModule(reactContext));
    
        return modules;
      }
    
    }
    

    MainApplication.java

    // MainApplication.java
    
    ...
    import com.your-app-name.CustomToastPackage; // <-- Add this line with your package name.
    ...
    
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
                new MainReactPackage(),
                new CustomToastPackage()); // <-- Add this line with your package name.
    }
    

    3. 在JavaScript中使用JavaModule

    Wrap the native module in a JavaScript module

    /**
     * This exposes the native ToastExample module as a JS module. This has a
     * function 'show' which takes the following parameters:
     *
     * 1. String message: A string with the text to toast
     * 2. int duration: The duration of the toast. May be ToastExample.SHORT or
     *    ToastExample.LONG
     */
    import {NativeModules} from 'react-native';
    module.exports = NativeModules.ToastExample;
    

    Use the module

    import ToastExample from './ToastExample';
    
    ToastExample.show('Awesome', ToastExample.SHORT);
    

    参考资料

    相关文章

      网友评论

          本文标题:React Native 初探

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