React Native调用原生组件
来源:互联网 发布:淘宝内裤店铺起名 编辑:程序博客网 时间:2024/06/05 10:15
在React Native开发过程中,有时候我们可能需要访问平台的API,但react Native还没有相应的实现,或者是React Native还不支持一些原生的属性,我们需要调用原生代码来实现,或者是我们需要复用一些原来的Java代码,这个时候我们就需要创建一个原生模块来自己实现对我们需要功能的封装。 相关文档可以参照官方的介绍。
实例
下面我们就通过实现一个自定义模块,来熟悉编写原生模块需要用的一些知识。该模块主要实现调用一些Android原生的功能,比如弹Toast,启动Activity等。
实现模块
首先来创建一个原生模块。一个原生模块是一个继承了 ReactContextBaseJavaModule 的Java类,它有一个必须实现的方法getName(),它返回一个字符串名字,在js中我们就使用这个名字调用这个模块;还有构造函数NativeModule。
public class MyNativeModule extends ReactContextBaseJavaModule { private final static String MODULE_NAME = "MyNativeModule"; private static final String TestEvent = "TestEvent"; private ReactApplicationContext mContext; public MyNativeModule(ReactApplicationContext reactContext) { super(reactContext); mContext = reactContext; } @Override public String getName() { return MODULE_NAME; } @Nullable @Override public Map<String, Object> getConstants() { final Map<String, Object> constants = new HashMap<>(); constants.put("SHORT", Toast.LENGTH_SHORT); constants.put("LONG", Toast.LENGTH_LONG); constants.put("NATIVE_MODULE_NAME", MODULE_NAME); constants.put(TestEvent, TestEvent); return constants; } @ReactMethod public void startActivity(){ Intent intent = new Intent(mContext,SecondActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); } @ReactMethod public void showToast(String msg, int duration){ Toast.makeText(mContext, msg, duration).show(); }}
这里需要对React Native和原生的类型映射做一个简单的介绍。详细的还可以参考ReadableMap和ReadableArray
Boolean -> BoolInteger -> NumberDouble -> NumberFloat -> NumberString -> StringCallback -> functionReadableMap -> ObjectReadableArray -> Array
例如,实现getContants方法导出需要给JavaScript使用的常量。
@Nullable @Override public Map<String, Object> getConstants() { final Map<String, Object> constants = new HashMap<>(); constants.put("SHORT", Toast.LENGTH_SHORT); constants.put("LONG", Toast.LENGTH_LONG); constants.put("NATIVE_MODULE_NAME", MODULE_NAME); constants.put(TestEvent, TestEvent); return constants; }
注册模块
接下来我们需要向系统注册这个模块,通过实现ReactPackage接口来实现。代码如下:
public class MyReactPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new MyNativeModule(reactContext)); return modules; } @Override public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); }}
添加模块
在Application的getPackages()方法中添加上面的模块。
@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), //添加的模块 new MyReactPackage() ); }
或者这MainActivity的onCreate中,添加如下代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReactRootView = new ReactRootView(this); mReactInstanceManager = ReactInstanceManager.builder() .setApplication(getApplication()) .setBundleAssetName("index.android.bundle") .setJSMainModuleName("index.android") .addPackage(new MainReactPackage()) .addPackage(new MyReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build(); mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null); setContentView(mReactRootView); }
Js端封装模块
为了使javascript端访问起来更为方便,通常我们都会把原生模块封装成一个JavaScript模块。
import { NativeModules } from 'react-native'; // 这里的MyNativeModule必须对应// public String getName()中返回的字符串export default NativeModules.MyNativeModule;
接下来,就可以直接使用了。
import MyNativeModule from './MyNativeModule'; class HelloWorld extends React.Component { startActivity(){ console.log("MODULE NAME: ",MyNativeModule.NATIVE_MODULE_NAME); MyNativeModule.startActivity(); } showToast(){ console.log("MODULE NAME: ",MyNativeModule.NATIVE_MODULE_NAME); MyNativeModule.showToast("From JS", MyNativeModule.LONG); } render() { return ( <View style={styles.container}> <TouchableOpacity onPress={this.startActivity}> <Text style={styles.hello}>start Activity</Text> </TouchableOpacity> </View> ) }}
其他知识
React Native的跨语言访问是异步进行的,所以想要给JavaScript返回一个值的唯一办法是使用回调函数或者发送事件。
回调函数
原生模块还支持一种特殊的参数——回调函数。它提供了一个函数来把返回值传回给JS。
@ReactMethod public void testCallback(int para1, int para2, Callback resultCallback){ int result = para1 + para2; resultCallback.invoke(result); }
也可以在JS中调用。例如:
testCallback(){ MyNativeModule.testCallback(100,100,(result) => { console.log("result: ",result); //'result: ', 200 }); }
原生模块通常只应调用回调函数一次。但是,它可以保存callback并在将来调用。
callback并非在对应的原生函数返回后立即被执行——注意跨语言通讯是异步的,这个执行过程会通过消息循环来进行。
RCTDeviceEventEmitter
生模块可以在没有被调用的情况下往JavaScript发送事件通知。最简单的办法就是通过RCTDeviceEventEmitter,这可以通过ReactContext来获得对应的引用。RCTDeviceEventEmitter相当于客户端的广播机制。
public void sendEvent(){ WritableMap params = Arguments.createMap(); params.putString("module", "MyNativeModule"); mContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit(TestEvent, params); }
在JS中调用的代码如下:
import { DeviceEventEmitter } from 'react-native';...... componentWillMount() { console.log("componentWillMount"); //接收事件 DeviceEventEmitter.addListener(MyNativeModule.TestEvent, info => { console.log(info); }); }
startActivityForResult
如果需要监听activity的生命周期事件(比如onResume, onPause等等),模块必须实现LifecycleEventListener,然后需要在构造函数中注册一个监听函数。
public MyNativeModule(ReactApplicationContext reactContext) { super(reactContext); mContext = reactContext; //添加监听 reactContext.addLifecycleEventListener(this); }
实现LifecycleEventListener的几个接口。
@Override public void onHostResume() { Log.e(MODULE_NAME, "onHostResume"); } @Override public void onHostPause() { Log.e(MODULE_NAME, "onHostPause"); } @Override public void onHostDestroy() { Log.e(MODULE_NAME, "onHostDestroy"); }
- React-native 调用原生组件
- React Native调用原生组件
- React Native调用Android原生组件
- React Native调用原生UI组件
- react native 调用原生UI组件
- React Native 原生平台调用React Native组件
- React Native使用原生组件
- react-native 调用原生方法
- Android React Native使用原生UI组件
- React Native十五:原生UI组件
- React Native使用指南-原生UI组件
- React Native 封装原生UI组件(iOS)
- React Native封装原生UI组件
- react-native iOS 原生组件 swift版
- React Native使用原生UI组件
- React Native 使用原生 UI 组件
- React Native调用开源组件库、安卓原生控件(Android端)
- 【react-native-0.31-iOS】封装原生组件并调用(02)
- 二维数组中的查找
- 读书笔记-人月神话16
- VM虚拟机安装Ubuntu以及Ubuntu的分辨率设置
- LeetCode-81.Search in Rotated Sorted Array II
- javascript 原型属性(prototype 属性)与 实例属性(自身属性)
- React Native调用原生组件
- 【无中生有】---16---大数据系统搭建
- Jquery插件jbox笔记
- Android初探FFmpeg(1)--在Windows下编译FFmpeg
- Spring下载word模板文件
- 个问题: 1、头文件重复包含 2、头文件加了ifndef条件预处理指令为什么还会定义
- spring如何可以同时访问静态资源和Action
- [Android]圆角视图
- 为什么程序员的工资那么高