Cordova:如何编写可以重复调用Javascript回调的原生插件?

2022-09-04 19:53:47

在开发Cordova插件时,我发现的所有教程都是这样的:

文件:真棒棒棒.js

var AwesomePlugin = {
  kungfuGripAction = function(target, successCallback, failureCallback) {
    return cordova.exec(
      successCallback,
      failureCallback,
      'AwesomePluginClass',
      'kungfuGripAction',
      [target]
    );
  }
};

module.exports = AwesomePlugin;

文件:AwesomePluginClass.java

@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
    if (ACTION_KUNGFU_GRIP.equals(action)) {
        JSONObject target = args.getJSONObject(0);
        if (gripTarget(target)) {
            callbackContext.success("Target successfully gripped.");
            return true;
        } else {
            callbackContext.error("Could not grip target.");
            return false;
        }
    }

    Log.d(LOG_TAG, "INVALID ACTION! " + action);
    callbackContext.error("Invalid action: " + action);
    return false;
}

文件:客户端代码.js

AwesomePlugin.kungfuGripAction(cobraEnemy, function(ok) { }, function(err) { });

在上面的代码中,回调只能调用一次,然后被释放。如果您尝试调用回调上下文对象的 or 方法,它将不起作用,您将收到一条日志消息:.success().error()

Attempted to send a second callback for ID: AwesomePlugin2982699494<BR>W/CordovaPlugin(976) Result was: "Target successfully gripped."

似乎不可能编写一个带有回调的方法,该回调可以重复调用,并且是从本机插件代码中调用回调的唯一记录方法。虽然这主要是我们想要的,但有时我们希望让插件重复执行回调。例如:.success().error()

AwesomePlugin.kungfuGripAction(cobraEnemy, function(ok) {
  // After successful grip, punch repeatedly and update life meter.
  AwesomePlugin.punchRepeatedly(cobraEnemy, function(hits) {
    updateLifeMeter(cobraEnemy, hits);
  }, function(err) { });
}, function(err) { });

AwesomePlugin.punchRepeatedly()上面将重复执行(可能在单独的线程中)并在每次成功执行时调用。如果以事实上的方式实现(使用一次性回调),则必须在回调中使用循环(这很糟糕,因为它是非异步的)或尾部调用(容易出错)。function(hits)AwesomePlugin.punchRepeatedly()

在本机代码中实现的正确方法是什么,以便它能够注册回调一次,然后重复执行它?punchRepeatedly()


答案 1

我认为,您可以使用属性设置为 .pluginResultkeepCallbacktrue

PluginResult result = new PluginResult(PluginResult.Status.OK, "YOUR_MESSAGE");
// PluginResult result = new PluginResult(PluginResult.Status.ERROR, "YOUR_ERROR_MESSAGE");
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);

您应该能够以这种方式多次调用回调。


答案 2

在乔纳斯的回答中,每次打电话时,你都必须发送相同的值。所以我更改了 PluginResult 类,以添加如下方法:sendPluginResult

 public void setStrMessage(String strMessage){
    this.strMessage = strMessage;
}

这样,我可以设置要发送到JavaScript端的消息。


推荐