有的时刻我们运用React Native没法满足一些运用特定场景,这个时刻就须要运用原生的Android要领,比方一些耗时的写操纵,操纵数据库或许多线程操纵等。
React Native能够直接挪用体系的API(java要领),完成JavaScript与java言语的通讯,假如React Native中没有满足我们需求的Api,能够封装原生的要领供应JavaScript挪用。
JavaScript和java通讯是经由过程bridge
完成的,在java层和JavaScript层的bridge离别存有雷同的一份模块设置表。Java与JavaScript互相通讯时,经由过程bridge里的设置表将所挪用模块体式格局转为{moduleID,methodID,args}
的情势传递给处置惩罚层,处置惩罚层经由过程bridge里的设置表找到对应的要领实行,假如有callback,则回传给挪用层,假如没有实行就完毕。
我们经由过程JavaScript挪用Toast的例子来看下,JavaScript怎样挪用Java代码的。
新建一个项目:
react-native init RNAndroid
在android的项目目次下面新建一个类RNToastModule,此类须要继续ReactContextBaseJavaModule
。
ReactContextBaseJavaModule
ReactContextBaseJavaModule
是一个抽象类,是用来被JavaScript挪用对象的父类,我们须要Override一些ReactContextBaseJavaModule
的要领。
起首要Override getName()
要领:
@Override
public String getName() {
return "RNToastAndroid";
}
这个要领的返回值就是JavaScript中挪用的称号,比方我们命名为RNToastAndroid,在JavaScript中能够如许挪用:
var {NativeModules}=require('react-native');
var rnToastAndroid = NativeModules.RNToastAndroid;
然后我们能够选择性的掩盖getConstants()
要领:
这个要领的用在JavaScript和Java直接定义公用常量的,它运用key-value的体式格局保留。
在Java中定义两个变量:
private static final String DURAION_SHORT_KEY = "SHORT";
private static final String DURAION_LONG_KEY = "LONG";
在getConstants()
中给两个字符串赋值:
@Override
public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put(DURAION_SHORT_KEY, Toast.LENGTH_SHORT);
constants.put(DURAION_LONG_KEY, Toast.LENGTH_LONG);
return constants;
}
我们把Toast的两个常量放在了 constants
中。
在JavaScript能够如许挪用:
rnToastAndroid.show('Hello Toast of native', rnToastAndroid.SHORT);
末了我们定义一个React挪用的要领:
@ReactMethod
public void show(String message, int duration) {
Toast.makeText(getReactApplicationContext(), message, duration).show();
}
这个运用了annotation
定义的体式格局必需加上@ReactMethod
。
这里的参数只能React Navive定义的参数。
ReactMethod的对应参数
@ReactMethod
中传的参数必需是JavaScript和Java对应的。
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array
注册ReactPackage
新建一个RNJavaReactPackage类,继续ReactPackage。
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new RNToastModule(reactContext));
return modules;
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return new ArrayList<>();
}
RNJavaReactPackage创建了一个NativeModule的List。把RNToastModule的实例都增加进去供应给JavaScript层挪用。
增加ReactPackage
在android/app/src/main/java/com/your-app-name/
中有个MainActivity.java个中的getPackages()
要领用来返回用来的ReactPackage包,增加定义好的RNJavaReactPackage的实例
以上内容已经在0.31.0
中更新。
新版本运用ReactNativeHost
替代ReactInstanceManager
,ReactNativeHost是设置Android相干设置的类。
须要在Application
中实例化。
起首完成新建一个ReactNativeHost
的实例并增加RNJavaReactPackage的实例:
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNJavaReactPackage()
);
}
};
完成ReactApplication
:
public class MainApplication extends Application implements ReactApplication {
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
JavaScript中挪用
在JavaScript显现Toast:
'use strict';
var {NativeModules}=require('react-native');
var rnToastAndroid = NativeModules.RNToastAndroid;
rnToastAndroid.show('Hello Toast of native', rnToastAndroid.SHORT);
如许就完成了从JavaScript中直接挪用了Java中定义的要领。