react native与android和iOS交互 (1) - LewinJun/reactNative GitHub Wiki

这里先介绍react native与native交互的几种方式

关键字: RCTBridgeMethod(RCTResponseSenderBlock,RCTResponseErrorBlock,RCTPromiseResolveBlock,RCTPromiseRejectBlock) RCTDeviceEventEmitter, Callback, Promise

iOS RCTBridgeMethod->RCTResponseSenderBlock

js主导,js调用一次,native返回一次(iOS提供给reactjs调用比android方便许多,后面再看安卓的交互方式就知道了)

  • iOS原生代码,实现RCTBridgeModule类的协议

PublicReactModules.h

#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

@interface PublicReactModules : NSObject<RCTBridgeModule>

@end

PublicReactModules.m

#import "PublicReactModules.h"

@implementation PublicReactModules
//导出此类为React NativeModules
RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(twoNumberTotal:(int)a b:(int)b callback:(RCTResponseSenderBlock)callback){
    callback(@[@(a + b)]);
}

RCT_EXPORT_METHOD(test:(NSString*)a){
    NSLog(@"%@", a);
}

@end
  • Android原生代码 PublicReactModules.java
import android.util.Log;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

/**
 * Created by lewin on 2017/7/26.
 */

public class PublicReactModules extends ReactContextBaseJavaModule {


    public PublicReactModules(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    //react  NativeModules调用的名称,iOS默认为类名,这里必须iOS和安卓名称一致,不然reactjs需要区分安卓还是iOS
    @Override
    public String getName() {
        return "PublicReactModules";
    }

    @ReactMethod
    public void test(String msg){
        Log.d("react",msg);
    }

    @ReactMethod
    public void twoNumberTotal(int a, int b, Callback callback){
        callback.invoke(a+b);
    }
}

添加package

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.ihr.reactnative.modules.PublicReactModules;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by lewin on 2017/7/26.
 * native与react交互包管理
 */

public class AppReactPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules=new ArrayList<>();
        
        modules.add(new PublicReactModules(reactContext));
        return modules;
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

    /**
     *
     * @param reactContext
     * @return 自定义View组件
     */
    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

最后就是要把AppReactPackage注入到react模块里面,当然是哪里调用哪里注入

public class ReactNativeActivity extends Activity implements DefaultHardwareBackBtnHandler {

    private final int MY_PERMISSIONS_REQUEST_READ_CONTACTS = 111;

    /**
     * react 布局view
     */
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mReactRootView = (ReactRootView)findViewById(R.id.react_view);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName(bundleAssetName)
                .setJSMainModuleName(jsMainModuleName)
                .addPackage(new MainReactPackage())
                //把自定义的package注入到react交互中心去
                .addPackage(new AppReactPackage())
                /**
                 * 调试模式下,建议直接写成 true 吧,我就因为这个错误,调了两天原因
                 */
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setUseDeveloperSupport(true)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();
        mReactRootView.startReactApplication(mReactInstanceManager, moduleName, null);

        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.SYSTEM_ALERT_WINDOW},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.facebook.react.ReactRootView
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:id="@+id/react_view"
        />
</LinearLayout>
  • reactjs调用部分代码,在 index.ios.js和index.android.js
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  NativeModules,
  Button,
  Alert,
  View
} from 'react-native';

export default class App extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>
          Welcome to zuo React Native hello react   fetch get post For android!
        </Text>
        <Text style={styles.instructions}>
          To get started, edit index.ios.js
        </Text>
        <Text style={styles.instructions}>
          Press Cmd+R to reload,{'\n'}
          Cmd+D or shake for dev menu
        </Text>
        <Button
            onPress={this._onPress}
            title="测试交互"
            color="#841584"
            accessibilityLabel="Learn more about this purple button"
      />
      <Button
          onPress={this._addPress}
          title="5+8等于多少?"
          color="#841584"
          accessibilityLabel="Learn more about this purple button"
    />
      </View>
    );
  }
  _onPress() {
    //PublicReactModules这个就是
    var publicUtil = NativeModules.PublicReactModules;
    publicUtil.test(data);
    }
  _addPress(){
    var PublicUtil= NativeModules.PublicUtil;
    PublicUtil.twoNumberTotal(5, 8,(msg)=>{
      Alert.alert(
            'Alert Title',
            "CallBack收到消息:"+msg,
          )
    });

  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  btn: {
        width: 100,
        height: 50,
        alignItems: 'center',
        justifyContent: 'center',
        alignSelf: 'center',
    },

    btnText: {
        fontSize: 18
    }
});
AppRegistry.registerComponent('reactLewinDemo', () => App);
⚠️ **GitHub.com Fallback** ⚠️