2

我有一个适用于 Android 和 iOS 的 Cordova 插件。但是,当移植到 Windows Phone 8 时它会失败,因为在 Cordova for Windows Phone 中似乎不支持多个未完成的回调。

问题是这样的:

当使用将 KeepCallback 设置为 true 的 PluginResult 调用 DispatchCommandResult 时,来自不同方法的进一步 DispatchCommand 将同时调用其回调和前一个回调(将 KeepCallback 设置为 true 的回调)。

更糟糕的是,如果第二个 DispatchCommandResult 的 PluginResult 将 KeepCallback 设置为 false(默认值),那么这将取消任何将 KeepCallback 设置为 true 的进一步回调。

示例

考虑下面的代码。这是对 Cordova Echo 样本的修改。

echo 方法将(通过 DispatchCommandResult)使用最初调用的相同字符串调用 javascript“成功”回调(经过几次 JSON 转换)

repeat 方法的作用与 echo 相同,只是它在单独的线程中每 5 秒重复调用一次 javascript 'success' 回调。

如果调用repeat,然后在调用echo 之后的某个时间点,则echo 方法中的DispatchCommandResult 将导致调用echo 成功和repeat 成功回调,然后阻止进一步的重复成功回调,因为KeepCallback 未设置为true。

在 Android 中,这个问题不是问题,因为 Cordova 提供了 callbackId。但是,对于 Windows Phone,callbackId 是不可访问的。

C# 代码

namespace Cordova.Extension.Commands
{
    public class Echo : BaseCommand
    {
        public void echo(string options)
        {
            string optVal = JsonHelper.Deserialize<string[]>(options)[0];
            DispatchCommandResult(new PluginResult(PluginResult.Status.OK, optVal));
        }
        public void repeat(string options)
        {
            string optVal = JsonHelper.Deserialize<string[]>(options)[0];
            ThreadStart worker = () =>
            {
                try
                {
                    while (true)
                    {
                        Thread.Sleep(5000);
                        PluginResult r = new PluginResult(PluginResult.Status.OK, optVal);
                        r.KeepCallback = true;
                        DispatchCommandResult(r);
                    }
                }
                catch (Exception ex)
                {
                    this.DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ex.Message));
                }
            };
            new Thread(worker).Start();
        }
    }
}

JavaScript 代码

function echo() {
    function success(message) {
        console.log("echo success: " + message);
    }
    function error(e) {
        console.log("echo error: " + e);
    }
    cordova.exec(success, error, "Echo", "echo", ["Hello"]);
}

function repeat() {
    function success(message) {
        console.log("repeat success: " + message);
    }
    function error(e) {
        console.log("repeat error: " + e);
    }
    cordova.exec(success, error, "Echo", "repeat", ["Hello again"]);
}

echo();
.
.
.
repeat();
.
.
.
echo();

样本输出

Log:"echo success: Hello"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello again"
Log:"repeat success: Hello"
Log:"echo success: Hello"

有没有其他人有这个问题?如果是这样,是否有解决方法?我做错什么了吗?

4

1 回答 1

1

我在使用cordova 2.5时遇到了同样的问题,这就是我发现的。

在(尚未发布的)cordova 2.8 版本中,如果您查看BaseCommand.cscordovalib 文件。您可以看到CurrentCommandCallbackId可用于跟踪您要调用的回调的 。

然后,如果您将 KeepCallback 设置为 false,您可以将命令分派给想要的回调。

PhoneGap 的当前版本是 2.7.0,因此要使用它,您必须克隆2.8 版本的 cordova并复制文件夹的Pluginscordovacordivalib的内容。templates/standalone

完成后,您可以通过以下方式使用此新功能:

private void DispatchMessage(PluginResult.Status status, string message, bool keepCallback, string callBackID)
{
    PluginResult res = new PluginResult(status, message);
    res.KeepCallback = keepCallback;
    DispatchCommandResult(res, callBackID);
}

但是,一旦 Phonegap 2.8 发布,使用 Cordova 的正式版本更新您的应用程序会更安全。

于 2013-05-30T12:12:10.167 回答