ReactNative原生Android交互

在开发中,我们经常遇到需要和原生交互的场景,ReactNative已经给我们预置了相关接口,接下来简单使用一下吧。

1.初始化一个空项目,用作示例:
react-native init Demo
cd Demo
react-native run-android
2.用Android Studio编写JAVA代码:

新建ToastModule类继承ReactContextBaseJavaModule,并实现父类抽象方法,其中getName()方法的返回值即是当前模块的名字。

####ReactNative调用:NativeModules.TestMode

public class ToastModule extends ReactContextBaseJavaModule{


    public ToastModule(@Nonnull ReactApplicationContext reactContext) {
        super(reactContext);
    }

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

重写public Map<String, Object> getConstants() 方法,提供变量供ReactNative使用。

####ReactNative调用:NativeModules.TestMode.SHORT

    private static final String DURATION_SHORT_KEY = "SHORT";
    private static final String DURATION_LONG_KEY = "LONG";

    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
        constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
        return constants;
    }

提供方法供ReactNative使用,需要添加@ReactMethod注解。

####ReactNative调用:NativeModules.TestMode.showToast(“测试输出”, NativeModules.TestMode.SHORT)

    @ReactMethod
    public void showToast(String message, int duration) {
        Toast.makeText(getReactApplicationContext(), message, duration).show();
    }

提供回调方法供ReactNative使用,需要添加@ReactMethod注解,回调函数使用ReactNative提供的Callback。

####ReactNative调用:NativeModules.TestMode.showCall((name, age, isMan) => {console.log(name + “+” + age + “+” + isMan)})

    @ReactMethod
    public void showCall(Callback callback) {
        callback.invoke("hello", 123, false);
    }

提供发送事件的方法供ReactNative使用,需要添加@ReactMethod注解。

####ReactNative调用:this.call = DeviceEventEmitter.addListener(‘event’, (data) => {console.log(“收到消息:”, data) });

    @ReactMethod
    public void sendEvent() {
        getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("event", count);
        count++;
    }

模块监听Activity生命周期,需要实现LifecycleEventListener接口。

    reactContext.addActivityEventListener(this);

    @Override
    public void onHostResume() {

    }

    @Override
    public void onHostPause() {

    }

    @Override
    public void onHostDestroy() {

    }

模块监听onActivityResult,需要实现ActivityEventListener接口。

    reactContext.addLifecycleEventListener(this);

    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {

    }

    @Override
    public void onNewIntent(Intent intent) {

    }
3.完整代码:

App.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */
import { NativeModules, DeviceEventEmitter } from "react-native";
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import TestRN from "./TestRN";


const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
  android:
    'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

type Props = {};
export default class App extends Component<Props> {

  constructor(props) {
    super(props)
    this.state = {
      one: '',
      two: '',
    }
  }


  componentDidMount() {
    this.call = DeviceEventEmitter.addListener('event', (data) => {
      console.log("收到消息:", data)
      this.setState({ one: data })
    });

    TestRN.showToast("测试输出", TestRN.SHORT)
    TestRN.showCall((name, age, isMan) => {
      console.log(name + "+" + age + "+" + isMan)
      this.setState({ two: name + "+" + age + "+" + isMan })
    })
  }

  componentWillMount() {
    this.call && this.call.remove()
  }


  render() {
    return (
      <TouchableOpacity style={styles.container} onPress={() => {
        TestRN.sendEvent()
      }}>
        <Text style={styles.welcome}>Demo测试</Text>
        <Text style={styles.instructions}>{this.state.one}</Text>
        <Text style={styles.instructions}>{this.state.two}</Text>
      </TouchableOpacity>
    );
  }
}

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,
  },
});

TestRN.js

import { NativeModules } from "react-native";
export default NativeModules.TestMode;

ToastModule.java

package com.demo;

import android.app.Activity;
import android.content.Intent;
import android.widget.Toast;

import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nonnull;

public class ToastModule extends ReactContextBaseJavaModule implements LifecycleEventListener, ActivityEventListener {
    private static final String DURATION_SHORT_KEY = "SHORT";
    private static final String DURATION_LONG_KEY = "LONG";
    private int count = 12580;

    public ToastModule(@Nonnull ReactApplicationContext reactContext) {
        super(reactContext);
        reactContext.addActivityEventListener(this);
        reactContext.addLifecycleEventListener(this);
    }

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

    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
        constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
        return constants;
    }

    @ReactMethod
    public void showToast(String message, int duration) {
        Toast.makeText(getReactApplicationContext(), message, duration).show();
    }

    @ReactMethod
    public void showCall(Callback callback) {
        callback.invoke("hello", 123, false);
    }

    @ReactMethod
    public void sendEvent() {
        getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("event", count);
        count++;
    }


    @Override
    public void onHostResume() {

    }

    @Override
    public void onHostPause() {

    }

    @Override
    public void onHostDestroy() {

    }

    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {

    }

    @Override
    public void onNewIntent(Intent intent) {

    }
}

ToastPackage.java

package com.demo;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Nonnull;

public class ToastPackage implements ReactPackage {

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

    @Nonnull
    @Override
    public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {

        return Collections.emptyList();
    }
}

MainApplication.java

package com.demo;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage(),
                    new ToastPackage()
            );
        }

        @Override
        protected String getJSMainModuleName() {
            return "index";
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }
}

4.顺序梳理:
  • 1.编写待调用的JAVA Module类,通过@ReactMethod注解暴露外部调用的方法。
  • 2.编写ReactPackage类,并在createNativeModules方法中添加Module中的类。
  • 3.在MainApplication中getPackages()中注册上面的ReactPackage类。
  • 4.编译apk,并在ReactNative中调用。
发布了122 篇原创文章 · 获赞 238 · 访问量 76万+

猜你喜欢

转载自blog.csdn.net/c__chao/article/details/90037286