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代码

package com.test;

import android.support.annotation.Nullable;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

abstract public class BaseModule extends ReactContextBaseJavaModule {

    protected ReactApplicationContext context;

    public BaseModule(ReactApplicationContext reactContext) {
        super(reactContext);
        context = reactContext;
    }

    /** * 原生层向js层发送数据 * @param eventName * @param params */
    protected void sendEvent(String eventName,@Nullable WritableMap params) {
        context
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName,params);
    }
}

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

自定义 Android 模组代码

package com.test;

import com.facebook.react.bridge.ReactApplicationContext;

public class TestModule extends BaseModule {

    public TestModule(ReactApplicationContext reactContext) {
        super(reactContext);
        context = reactContext;
    }

    @Override
    public String getName() {
        return "Test";
    }

    @ReactMethod
    public void test(String text) {
        WritableMap event = Arguments.createMap();
        event.putString("text",text);
        sendEvent("testEvent",event);
    }
}

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

import {
    NativeModules,DeviceEventEmitter
} from 'react-native';

const listeners = {};
const TestModule = NativeModules.Test;

export default class Test {

    static test(text) {
        TestModule.test(text);
    }

    static addTestListener(cb) {
        listeners[cb] = DeviceEventEmitter.addListener('testEvent',resp => {
            cb(resp);
        });
    }

    static removeTestListener(cb) {
        if (!listeners[cb]) {
            return;
        }
        listeners[cb].remove();
        listeners[cb] = null;
    }
}

2. RN 同 View 通讯

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

package com.test;

import android.support.annotation.Nullable;

import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.facebook.react.views.view.ReactViewGroup;

import java.util.Map;

/** * Created by chenwenyu on 17-8-27. */

public class TestViewManager extends ViewGroupManager<MyCustomView> {

    private ThemedReactContext mReactContext;

    public static final int UPDATE_DATA = 1;

    @Override
    public String getName() {
        return "TestView";
    }

    @Override
    protected MyCustomView createViewInstance(ThemedReactContext reactContext) {
        mReactContext = reactContext;
        return new MyCustomView(reactContext);
    }

    @Override
    public Map<String,Integer> getCommandsMap() {
        return MapBuilder.of(
                "updateData",TestViewManager.UPDATE_DATA
        );
    }

    @Override
    public void receiveCommand(MyCustomView view,int commandType,@Nullable ReadableArray args) {

        switch (commandType) {
            case TestViewManager.UPDATE_DATA:
                updateData(view,args.getMap(0));
                break;
            default:
                throw new JSApplicationIllegalArgumentException(String.format(
                        "Unsupported commadn %d received by $s",commandType,this.getClass().getSimpleName()
                ));
        }
    }

    @ReactProp(name = "visibility")
    public void setVisibility(ReactViewGroup reactViewGroup,int visibility) {
        reactViewGroup.setVisibility(visibility);
    }

    /** * 原生层向js层发送数据 * @param eventName * @param params */
    private void sendEvent(MyCustomView myCustomView,String eventName,@Nullable WritableMap params) {
        WritableMap event = Arguments.createMap();
        event.putMap("params",params);
        event.putString("type",eventName);
        mReactContext
                .getJSModule(RCTEventEmitter.class)
                .receiveEvent(myCustomView.getId(),"topChange",event);
    }

    private void updateData(MyCustomView myCustomView,ReadableMap option) {
        if (option != null) {
            String data = option.getString("data");
            data += "data:" + data;
            WritableMap writableMap = Arguments.createMap();
            writableMap.putString("callData",data);
            sendEvent(myCustomView,"test",writableMap);
        }
    }
}

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

import {
  requireNativeComponent
} from 'react-native';

import React,{
  PureComponent
} from 'react';

import react_native from 'react-native';
var RCTTestView = react_native.UIManager.TestView;
var Commands = RCTTestView.Commands;
var COMMAND_UPDATE_DATA = Commands.updateData; //同原生层getCommandsMap相对应

export default class TestView extends PureComponent {

  constructor() {
    super();
  }

  _onChange(event) {
    if (typeof this.props[event.nativeEvent.type] === 'function') {
      this.props[event.nativeEvent.type](event.nativeEvent.params);
    }
  }

  updateData(data) {
    react_native.UIManager.dispatchViewManagerCommand(react_native.findNodeHandle(this),COMMAND_UPDATE_DATA,[data]);
  }

  render() {
      return <TestShowView visibility={1} onChange={this._onChange.bind(this)}/>;
  }
}

const TestShowView = requireNativeComponent('TestView',TestView,{
  nativeOnly: {
    onChange: true
  }
});

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

原文链接:https://www.f2er.com/react/303027.html

猜你在找的React相关文章