ReactNative开发还不会跟android交互通信吗?赶快看一下这篇文章,瞬间豁然开朗-原来跨平台调用原生方法竟然如此简单

React Native 与 Android 原生通信全攻略

“这个功能React Native实现不了,得用原生!” —— 当你听到这句话时别慌,React Native与Android的通信桥梁比你想象的更强大。本文将带你深入探索RN与Android原生的各种通信方式,让你轻松驾驭混合开发!

一、通信原理总览

1.1 React Native架构简析

  • JS层:运行JavaScript代码
  • Native层:运行原生Java/Kotlin代码
  • Bridge:负责双向通信的异步通道

1.2 三种核心通信方式

方式 方向 适用场景 性能
原生模块 Native→JS 调用原生功能
原生组件 JS→Native 自定义UI组件
事件机制 Native→JS 原生事件通知

二、创建原生模块(Native→JS)

2.1 基础模块创建步骤

1. 创建原生模块类

// ToastModule.java
public class ToastModule extends ReactContextBaseJavaModule {
    private final ReactApplicationContext reactContext;

    public ToastModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @Override
    public String getName() {
        return "ToastExample"; // JS中引用的名称
    }

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

2. 创建Package类

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

    @Override
    public List<ViewManager> createViewManagers(
        ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

3. 注册Package

// MainApplication.java
@Override
protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new CustomToastPackage() // 添加自定义包
    );
}

4. JS端调用

import { NativeModules } from 'react-native';
const { ToastExample } = NativeModules;

ToastExample.show('Hello from Native!', ToastExample.LONG);

三、创建原生UI组件(JS→Native)

3.1 自定义View组件

1. 创建ViewManager

public class CustomViewManager extends SimpleViewManager<TextView> {
    @Override
    public String getName() {
        return "CustomNativeView";
    }

    @Override
    protected TextView createViewInstance(ThemedReactContext context) {
        TextView textView = new TextView(context);
        textView.setText("This is native TextView");
        return textView;
    }

    @ReactProp(name="text")
    public void setText(TextView view, String text) {
        view.setText(text);
    }
}

2. 注册到Package

@Override
public List<ViewManager> createViewManagers(
    ReactApplicationContext reactContext) {
    return Arrays.<ViewManager>asList(
        new CustomViewManager()
    );
}

3. JS端使用

import { requireNativeComponent } from 'react-native';

const CustomNativeView = requireNativeComponent('CustomNativeView');

const App = () => (
  <View style={{flex: 1}}>
    <CustomNativeView 
      text="Hello from JS!" 
      style={{width: 200, height: 100}} 
    />
  </View>
);

四、事件通信(Native→JS)

4.1 发送事件到JS

1. 原生端发送事件

// 在原生模块中添加方法
private void sendEvent(ReactContext reactContext,
                      String eventName,
                      @Nullable WritableMap params) {
    reactContext
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
        .emit(eventName, params);
}

// 调用示例
WritableMap params = Arguments.createMap();
params.putString("message", "Native Event!");
sendEvent(reactContext, "onCustomEvent", params);

2. JS端监听事件

import { DeviceEventEmitter } from 'react-native';

useEffect(() => {
  const subscription = DeviceEventEmitter.addListener(
    'onCustomEvent',
    (event) => console.log(event.message)
  );
  return () => subscription.remove();
}, []);

五、高级通信技巧

5.1 Promise异步回调

1. 原生模块实现

@ReactMethod
public void asyncTask(String input, Promise promise) {
    try {
        String result = doComplexWork(input);
        promise.resolve(result);
    } catch (Exception e) {
        promise.reject("ERROR_CODE", e.getMessage());
    }
}

2. JS端调用

ToastExample.asyncTask('input')
    .then(result => console.log(result))
    .catch(error => console.error(error));

5.2 直接调用常量

1. 暴露常量

@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);
    return constants;
}

2. JS端使用

ToastExample.show('Hello', ToastExample.LONG);

六、性能优化策略

6.1 减少跨桥通信

  • 批量传输数据
  • 避免高频次通信
  • 对大文件使用原生路径而非base64

6.2 线程优化

@ReactMethod(isBlockingSynchronousMethod = true)
public String syncMethod() {
    // 同步方法(谨慎使用)
}

6.3 内存管理

  • 及时移除事件监听
  • 避免在原生端持有JS引用

七、调试技巧

7.1 检查模块注册

adb logcat | grep ReactNativeJS

7.2 Chrome调试

console.log(NativeModules); // 查看所有原生模块

7.3 React DevTools

检查原生组件层级结构

八、企业级实践方案

8.1 统一通信协议

public interface NativeBridge {
    @ReactMethod
    void invoke(String method, ReadableMap params, Promise promise);
}

8.2 安全校验

private boolean verifyRequest(String token) {
    // 实现安全验证逻辑
}

8.3 监控统计

private void trackApiCall(String methodName) {
    // 上报调用统计
}

总结:跨平台打破平台边界

记得第一次成功调通RN与原生通信时,那种突破次元壁的兴奋感至今难忘。当你在RN中调用原生相机API获得流畅体验,或者在原生代码中触发RN界面更新时,你会明白:真正的混合开发高手,能在JS和Native的世界自由穿梭

当你把这些技术应用到实际项目中时,你会发现:React Native与原生通信不是限制,而是有无限可能


如果觉得写的不错,请动动手指点赞、关注、评论哦
如有疑问,可以评论区留言~

你可能感兴趣的:(React-Native,react,native,android,交互)