React Native是啥?
是一款用JavaScriptScript编写原生(Android,iOS)应用的框架。
原理是啥?
总体来看,整套React Native框架分为三层,如下图所示:
- 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应用通信桥结构图如下所示:
Java 调用 JS
JS 调用 Java
启动流程
JavaScript层组件渲染
从上图我们可以很容易看出,Java层的组件渲染分为以下几步:
- JS层通过C++层把创建View的请求发送给Java层的UIManagerModule。
- UIManagerModule通过UIImplentation对操作请求进行包装。
- 包装后的操作请求被发送到View处理队列UIViewOperationQueue队列中等待处理。
- 实际处理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
顺利执行完后显示如下结果,
根据提示可以通过扫码在手机上看到代码运行效果
项目目录结构
React Native使用JSX写项目的。
JSX is a syntax extension to JavaScript.
Introducing JSX
Basic
Hello World
布局
列表
网络请求
自定义控件
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 工程目录结构
JS 工程中的Android 工程结构
MainApplication.java
MainActivity.java
ReactActivity.java
ReactActivityDelegate.java
ReactNativeHost.java
ReactNativeHost-structure
ReactNativeHost-createReactInstanceManager
ReactNativeHost-getMainModuleName
index.js
App.js
Android的 生命周期事件 是如何分发到 JS的世界 中的
ReactActivityDelegate
ReactInstanceManager
ReactContext
LifecycleEventListener
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);