【问题标题】:Call JavaScript method from Java React Native从 Java React Native 调用 JavaScript 方法
【发布时间】:2017-01-10 22:06:29
【问题描述】:

我是 React Native 的新手,但想知道是否可以从 Java 调用 React Native JavaScript 方法?我有一个小众设备,它有一个物理按钮,我想在按下时触发一个方法。

我看过下面这个插件https://github.com/artemyarulin/react-native-eval,但是Android实现好像已经过时了。

我已经用谷歌搜索了所有的例子,但我能找到的所有示例都是从 React Native 调用 Java 方法的参考,而不是相反。

非常感谢。

编辑

我尝试使用下面@ide 建议的方法来实施解决方案。到目前为止,这是我的尝试:

在我的 MainActivity 我有:

private String latestBarcode = "";

...

public String getLastestBarcode() {
  return this.latestBarcode;
}

public void setLatestBarcode(String barcode) {
  this.latestBarcode = barcode;
}

@Override
public void onBarcodeEvent(final BarcodeReadEvent event) {
  runOnUiThread(new Runnable(){
    @Override
    public void run() {
      String barcodeData = event.getBarcodeData();
      String tstp = event.getTimestamp();
      setLatestBarcode(barcodeData);
      Log.d("MainActivity", " TEST - barcodeData "+ barcodeData + " tstp : "+ tstp);
    }
  });
}
...

当用户按下物理硬件按钮时,此代码从设备获取条形码值。

在我的自定义 React Native 模块中

@ReactMethod
public void latestBarcode(Callback callback) {
  final Activity activity = getCurrentActivity();

  if(activity != null && activity instanceof MainActivity){
    callback.invoke(((MainActivity) activity).getLastestBarcode());
  }
  else {
    callback.invoke("");
  }
}

此方法获取值并将其公开给 React Native。这很有效,我可以读取该值,但我需要在用户按下按钮时触发一个方法,所以这是我的 React Native 模块,因为它现在完全是:

import android.app.Activity;
import android.util.Log;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;

import javax.annotation.Nullable;

// Import MainActivity
import com.myapp.MainActivity;

public class HoneywellCT50Module extends ReactContextBaseJavaModule {
  private ReactContext reactContext;

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


  @ReactMethod
  public void latestBarcode(Callback callback) {
    final Activity activity = getCurrentActivity();

    if(activity != null && activity instanceof MainActivity){
      WritableMap params = Arguments.createMap(); // <--- Added WritableMap
      sendEvent("BarcodeRecieved", params); // <--- Added sendEvent

      callback.invoke(((MainActivity) activity).getLastestBarcode());
    }
    else {
      callback.invoke("");
    }
  }

  // Added sendEvent
  private void sendEvent(
    String eventName,
    @Nullable WritableMap params
  ) {
    this.reactContext
      .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
      .emit(eventName, params);
  }


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

在 React Native 中:

// I import DeviceEventEmitter
import { DeviceEventEmitter } from 'react-native'

componentDidMount () {
  // Listen for Honeywell Scans
  DeviceEventEmitter.addListener('BarcodeRecieved', this.getBarcodeValue)
}

// I want to trigger this method
getBarcodeValue () {
  console.log('Event Received')
  // This gets the barcode value, works ok
  HoneywellCT50.latestBarcode((value) => {
    this.setState({ barcode: value })
  })
}

使用上面的代码,我可以构建没有 Java/构建错误的项目,并且我没有看到 JS 错误,但我无法触发事件。任何人都可以从这里帮助我指出正确的方向吗?

【问题讨论】:

    标签: java react-native


    【解决方案1】:

    您想要做的是从 Java 发出一个发送到 JavaScript 的事件。您将编写一个自定义本机模块,从 JavaScript 订阅其事件,然后在您的本机代码中发出该事件。请参阅本指南:http://facebook.github.io/react-native/docs/native-modules-android.html#sending-events-to-javascript

    【讨论】:

    • @ide 我已尝试根据您的回答实施解决方案,并添加了上面的代码。你对我哪里出错有什么建议吗?
    • 从 Java 向 JavaScript 发送事件似乎在最新 RN 版本(至少 44 和 45)的文档中消失了
    【解决方案2】:

    好的,所以我得到了一些代码。我不确定这是否是最好的解决方案,但现在我的理解有限,欢迎就以下问题提供任何反馈:

    MainActivity.java

    @Override
    public void onBarcodeEvent(final BarcodeReadEvent event) {
      runOnUiThread(new Runnable(){
        @Override
        public void run() {
          String barcodeData = event.getBarcodeData();
          String tstp = event.getTimestamp();
          setLatestBarcode(barcodeData);
          Log.d("MainActivity", " TEST - barcodeData "+ barcodeData + " tstp : "+ tstp);
        }
      });
    
      WritableMap params = Arguments.createMap(); // <--- added
    
      getReactInstanceManager().getCurrentReactContext() // <--- added
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) // <--- added
        .emit("BarcodeReceived", params); // <--- added
    }
    

    这行得通,我可以通过在我的 JS 中使用以下内容来触发 React 方法:

    componentWillUnmount () {
      this._barcodeListener.remove()
    }
    
    componentWillMount () {
      // Listen for Honeywell Scans
      this.getBarcodeValue = DeviceEventEmitter.addListener('BarcodeReceived', this.getBarcodeValue)
    }
    
    ...
    
    getBarcodeValue () {
      console.log('Event Received')
    
      HoneywellCT50.latestBarcode((value) => {
        this.setState({ barcode: value }, () => {
          console.log(this.state.barcode)
        })
      })
    }
    

    如果有经验的人读到这篇文章,我很想知道为什么我在上面的 EDIT 中发布的代码不起作用。是因为我尝试在 @ReactMethod 中发出事件吗?

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-01-03
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多