React Native 与原生层通讯(Android)

前端之家收集整理的这篇文章主要介绍了React Native 与原生层通讯(Android)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

React Native开发中不可避免涉及到到同原生交互通讯,FB 官方封装了一系列的跨平台组件,但是总是不能面面俱到的,所以很多组件还是需要我们自己去封装,实现同原生层交互。
Android自定义扩展包括两部分,一个是module,一个是View,这两个部分js层同其交互方法有所不同。

1. RN 同 Module 通讯

步骤一:创建一个 BaseModule 的抽象类,BaseModule 继承自ReactContentBaseJavaModule,然后在内部定义一个方法sendEvent,用来向js层发送数据,当其它 Android 模块继承 BaseModule,可以直接调用 sendEvent 方法,发送数据给 js 层,js 只需要监听对应方法名,就可以获得发送过来的值。

BaseModule代码

  1. package com.test;
  2.  
  3. import android.support.annotation.Nullable;
  4.  
  5. import com.facebook.react.bridge.ReactApplicationContext;
  6. import com.facebook.react.bridge.ReactContextBaseJavaModule;
  7. import com.facebook.react.bridge.WritableMap;
  8. import com.facebook.react.modules.core.DeviceEventManagerModule;
  9.  
  10. abstract public class BaseModule extends ReactContextBaseJavaModule {
  11.  
  12. protected ReactApplicationContext context;
  13.  
  14. public BaseModule(ReactApplicationContext reactContext) {
  15. super(reactContext);
  16. context = reactContext;
  17. }
  18.  
  19. /** * 原生层向js层发送数据 * @param eventName * @param params */
  20. protected void sendEvent(String eventName,@Nullable WritableMap params) {
  21. context
  22. .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
  23. .emit(eventName,params);
  24. }
  25. }

步骤二:然后创建一个 Android 模块继承 BaseModule,然后使用 @ReactMethod 来标记那些你希望通过Js来访问的方法

自定义 Android 模组代码

  1. package com.test;
  2.  
  3. import com.facebook.react.bridge.ReactApplicationContext;
  4.  
  5. public class TestModule extends BaseModule {
  6.  
  7. public TestModule(ReactApplicationContext reactContext) {
  8. super(reactContext);
  9. context = reactContext;
  10. }
  11.  
  12. @Override
  13. public String getName() {
  14. return "Test";
  15. }
  16.  
  17. @ReactMethod
  18. public void test(String text) {
  19. WritableMap event = Arguments.createMap();
  20. event.putString("text",text);
  21. sendEvent("testEvent",event);
  22. }
  23. }

步骤三:最后在 js 层调用 native 层方法,并监听 native 返回。一般写第三方模块的话会写一个 index.js 文件,统一实现这些方法。使用DeviceEventEmitter.addListener监听native层返回,若只是想触发一次监听,那可以使用DeviceEventEmitter.once。

  1. import {
  2. NativeModules,DeviceEventEmitter
  3. } from 'react-native';
  4.  
  5. const listeners = {};
  6. const TestModule = NativeModules.Test;
  7.  
  8. export default class Test {
  9.  
  10. static test(text) {
  11. TestModule.test(text);
  12. }
  13.  
  14. static addTestListener(cb) {
  15. listeners[cb] = DeviceEventEmitter.addListener('testEvent',resp => {
  16. cb(resp);
  17. });
  18. }
  19.  
  20. static removeTestListener(cb) {
  21. if (!listeners[cb]) {
  22. return;
  23. }
  24. listeners[cb].remove();
  25. listeners[cb] = null;
  26. }
  27. }

2. RN 同 View 通讯

步骤一: 继承自ViewGroupManager,使用 @ReactProp(name = “xx”) 来传递props值到native层中,如果想通过方法从 js 层传值过来,就需要在 native 层重写 getCommandsMap 和 receiveCommand,在 receiveCommand 通过 type 值获得从 js 层不同调用传递过来的数据 。

  1. package com.test;
  2.  
  3. import android.support.annotation.Nullable;
  4.  
  5. import com.facebook.react.bridge.Arguments;
  6. import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
  7. import com.facebook.react.bridge.ReadableArray;
  8. import com.facebook.react.bridge.ReadableMap;
  9. import com.facebook.react.bridge.WritableMap;
  10. import com.facebook.react.common.MapBuilder;
  11. import com.facebook.react.uimanager.ThemedReactContext;
  12. import com.facebook.react.uimanager.ViewGroupManager;
  13. import com.facebook.react.uimanager.annotations.ReactProp;
  14. import com.facebook.react.uimanager.events.RCTEventEmitter;
  15. import com.facebook.react.views.view.ReactViewGroup;
  16.  
  17. import java.util.Map;
  18.  
  19. /** * Created by chenwenyu on 17-8-27. */
  20.  
  21. public class TestViewManager extends ViewGroupManager<MyCustomView> {
  22.  
  23. private ThemedReactContext mReactContext;
  24.  
  25. public static final int UPDATE_DATA = 1;
  26.  
  27. @Override
  28. public String getName() {
  29. return "TestView";
  30. }
  31.  
  32. @Override
  33. protected MyCustomView createViewInstance(ThemedReactContext reactContext) {
  34. mReactContext = reactContext;
  35. return new MyCustomView(reactContext);
  36. }
  37.  
  38. @Override
  39. public Map<String,Integer> getCommandsMap() {
  40. return MapBuilder.of(
  41. "updateData",TestViewManager.UPDATE_DATA
  42. );
  43. }
  44.  
  45. @Override
  46. public void receiveCommand(MyCustomView view,int commandType,@Nullable ReadableArray args) {
  47.  
  48. switch (commandType) {
  49. case TestViewManager.UPDATE_DATA:
  50. updateData(view,args.getMap(0));
  51. break;
  52. default:
  53. throw new JSApplicationIllegalArgumentException(String.format(
  54. "Unsupported commadn %d received by $s",commandType,this.getClass().getSimpleName()
  55. ));
  56. }
  57. }
  58.  
  59. @ReactProp(name = "visibility")
  60. public void setVisibility(ReactViewGroup reactViewGroup,int visibility) {
  61. reactViewGroup.setVisibility(visibility);
  62. }
  63.  
  64. /** * 原生层向js层发送数据 * @param eventName * @param params */
  65. private void sendEvent(MyCustomView myCustomView,String eventName,@Nullable WritableMap params) {
  66. WritableMap event = Arguments.createMap();
  67. event.putMap("params",params);
  68. event.putString("type",eventName);
  69. mReactContext
  70. .getJSModule(RCTEventEmitter.class)
  71. .receiveEvent(myCustomView.getId(),"topChange",event);
  72. }
  73.  
  74. private void updateData(MyCustomView myCustomView,ReadableMap option) {
  75. if (option != null) {
  76. String data = option.getString("data");
  77. data += "data:" + data;
  78. WritableMap writableMap = Arguments.createMap();
  79. writableMap.putString("callData",data);
  80. sendEvent(myCustomView,"test",writableMap);
  81. }
  82. }
  83. }

步骤二:js层调用,可以通过直接设置props的值向原生层传递值,也可以通过dispatchViewManagerCommand传递值

  1. import {
  2. requireNativeComponent
  3. } from 'react-native';
  4.  
  5. import React,{
  6. PureComponent
  7. } from 'react';
  8.  
  9. import react_native from 'react-native';
  10. var RCTTestView = react_native.UIManager.TestView;
  11. var Commands = RCTTestView.Commands;
  12. var COMMAND_UPDATE_DATA = Commands.updateData; //同原生层getCommandsMap相对应
  13.  
  14. export default class TestView extends PureComponent {
  15.  
  16. constructor() {
  17. super();
  18. }
  19.  
  20. _onChange(event) {
  21. if (typeof this.props[event.nativeEvent.type] === 'function') {
  22. this.props[event.nativeEvent.type](event.nativeEvent.params);
  23. }
  24. }
  25.  
  26. updateData(data) {
  27. react_native.UIManager.dispatchViewManagerCommand(react_native.findNodeHandle(this),COMMAND_UPDATE_DATA,[data]);
  28. }
  29.  
  30. render() {
  31. return <TestShowView visibility={1} onChange={this._onChange.bind(this)}/>;
  32. }
  33. }
  34.  
  35. const TestShowView = requireNativeComponent('TestView',TestView,{
  36. nativeOnly: {
  37. onChange: true
  38. }
  39. });

当了解了 js 层同 Android 原生层通讯之后,你就可以自己扩展封装一些组件供自己所用了。

猜你在找的React相关文章