首页 > 代码库 > Cordova框架基本原理

Cordova框架基本原理

最近在做混编项目,也是从项目里开始接触Cordova框架,网上很多帖子都总结的很好,我还是要总结一下,便于加深一下。

Cordova框架是一个可以让JS与原生代码(包括 Android 的 java,iOS 的 Objective-C 等)互相通信的一个库,并且提供了一系列的插件类,比如 JS 直接操作本地数据库的插件类。

要想明白它是如何互相通信的需要弄清楚下面三个问题:

1.JS怎么跟Objective-C通信

2.Objective-C怎么跟JS通信

3.JS请求Objective-C,Objective-C返回结果给JS,这样一来一往是怎么串起来的

 

JS与OC通信的关键代码在框架中Cordova.js文件中:

首先, HTML中需要加载Cordova.js

<script type="text/javascript" src=http://www.mamicode.com/"cordova.js"></script>

然后JS调用原生:

// successCallback : 成功的回调方法
// failCallback : 失败的回调方法
// server : 所要请求的服务名字,就是插件类的名字
// action : 所要请求的服务具体操作,其实就是Native 的方法名,字符串。
// actionArgs : 请求操作所带的参数,这是个数组。
cordova.exec(successCallback, failCallback, service, action, actionArgs);

cordova.js里定义的一个 var结构体,里面有一些方法以及其他变量,关于exec ,可以看 iOSExec这个js 方法,穿进来的这五个参数并不会直接传给原生,cordova.js会先做这样的处理:

  1. 会为每个请求生成一个叫 callbackId 的唯一标识:这个参数需传给 Objective-C 端,Objective-C 处理完后,会把 callbackId 连同处理结果一起返回给 JS 端
  2. 以 callbackId 为 key,{success:successCallback, fail:failCallback} 为 value,把这个键值对保存在 JS 端的字典里,successCallback 与 failCallback 这两个参数不需要传给 Objective-C 端,Objective-C 返回结果时带上 callbackId,JS 端就可以根据 callbackId 找到回调方法
  3. 每次 JS 请求,最后发到 Objective-C 的数据包括:callbackId, service, action, actionArgs 。

那么iOSExec又是怎么调用原生的呢:

实际上就是做一个假的url,在原生的webview中进行拦截。

原生代码拿到 callbackId、service、action 及 actionArgs 后,会做以下的处理:

  1. 根据 service 参数找到对应的插件类
  2. 根据 action 参数找到插件类中对应的处理方法,并把 actionArgs 作为处理方法请求参数的一部分传给处理方法
  3. 处理完成后,把处理结果及 callbackId 返回给 JS 端,JS 端收到后会根据 callbackId 找到回调方法,并把处理结果传给回调方法  

关键代码:

- (void)sendPluginResult:(CDVPluginResult*)result callbackId:(NSString*)callbackId
{
    CDV_EXEC_LOG(@"Exec(%@): Sending result. Status=%@", callbackId, result.status);
    // This occurs when there is are no win/fail callbacks for the call.
    if ([@"INVALID" isEqualToString : callbackId]) {
        return;
    }
    int status = [result.status intValue];
    BOOL keepCallback = [result.keepCallback boolValue];
    NSString* argumentsAsJSON = [result argumentsAsJSON];

    // 将请求的处理结果及 callbackId 通过调用 JS 方法返回给 JS 端
    NSString* js = [NSString stringWithFormat:
                                @"cordova.require(‘cordova/exec‘).nativeCallback(‘%@‘,%d,%@,%d)", 
                                callbackId, status, argumentsAsJSON, keepCallback];

    [self evalJsHelper:js];
}
// 根据 callbackId 及是否成功标识,找到回调方法,并把处理结果传给回调方法
callbackFromNative: function(callbackId, success, status, args, keepCallback) {
       var callback = cordova.callbacks[callbackId];
       if (callback) {
           if (success && status == cordova.callbackStatus.OK) {
               callback.success && callback.success.apply(null, args);
           } else if (!success) {
               callback.fail && callback.fail.apply(null, args);
           }

           // Clear callback if not expecting any more results
           if (!keepCallback) {
               delete cordova.callbacks[callbackId];
           }
       }
   }

JS 端根据 callbackId 回调。

 

Cordova框架基本原理