[Cordova学习]4.Cordova(iOS)架构和实现

JS和Native的通信原理


图中表示的是默认的JS和Native通信的方法(采用iframe)

  1. 保存Cordova_plugin.js的 插件文件名字和地址。
  2. 插件的API呼出时,通过调用Cordova的exec模块将API的参数保存在CommandQueue的队列中。  CALLBACK则保存在JS侧的callbacks map里面。
  3. 添加一个空的iframe,iframe的src则指向gap://ready
  4. 3的iframe的src设置以后,NATIVE侧UIWebviewDelegate#shouldStartLoadWithRequest则被呼出来。
  5.  Webview的Delegatet判断gap://ready的情况下,则执行commandDelegate的处理。
  6. commandDelegate则从JS侧取出API的参数,内部实现则是通过 UIWebview#stringByEvaluatingJavaScriptFromString的返回值 取得CommandQueue里面的参数转换成JSON数据。
  7. 根据6的插件,执行NATIVE定义的插件实例。
  8. 插件中,有CALLBACK的情况下,成功失败的结果通过UIWebview#stringByEvaluatingJavaScriptFromString执行JS,JS端则根据传过来的CALLBACKID,从callbacks map取出回调函数并执行。


例:camera插件呼出的时序图

JS到Natvie通信方式

从JS到Natvie的主要的通信方式有2种

  1. iframe的方法(默认)     

           该方法是添加iframe到html元素中,并设置iframe的src为指定gap://ready,触发NATIVE侧UIWebview#shouldStartLoadWithRequest的方法。插件的参数则
           再从JS侧的JSON数据取过来。插件的方法执行完了为止都是同步处理。

        2.xmlHttpRequest的方法(iOS5.x版本因为 -webkit-scroll的IFRAME有BUG,则推荐使用)

         JS侧没有明确定义这个XHR的方法则不可使用。插件具体的参数内容则设置在了头部信息。
     execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);     
     execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());     
    Native侧NSURLRequest的协议,根据是否为/!gap_exec来判定需要拦截。
    /!gap_exec的时候,则从头部取得插件的具体参数。

      通信模式切换的方法下面链接有记载
      https://github.com/phonegap/phonegap/blob/master/lib/ios/guides/Changing%20the%20JavaScript%20to%20Native%20Bridge%20Mode.md    
      deviceready的事件处理中,执行XHR模式或者iframe模式的切换。    

var exec = cordova.require('cordova/exec'); 
exec.setJsToNativeBridgeMode(exec.jsToNativeModes.XHR_OPTIONAL_PAYLOAD);
var exec = cordova.require('cordova/exec'); 
exec.setJsToNativeBridgeMode(exec.jsToNativeModes.IFRAME_NAV);

插件导入流程

Natvie侧

  1. APP启动,MainViewController初始化之时,queue和command的DELEGATE初期化
  2. config.xml文件解析,插件名设置到数组,插件文件和插件名设置到pluginMap,属性设置到setting
  3. 在Webview类里面,加载index.html,index.html里面加载cordova.js、开始初期化


JS侧

  1. 加载cordova.js时、内部的事件设置模块,NATIVE交互模块,初期化模块,插件加载
  2. 插件模块是cordova_plugins.js文件定义的插件文件地址,文件名保存的MAP。
  3. deviceready事件发布后,插件的API可以使用了。
  4. 插件API执行后,模块MAP将插件文件加载,执行exec函数。
  5.  在index.html里面添加一个空的iframe、指定src=gap://ready,通知到Nativie侧。



Cordova本体的各个组的构造图



说明
Staging组JS侧的组。平台不同,cordova.js和config.xml写法不同
Plugins组Native侧的插件组。添加的插件放在这个组
Classes组app启动的appDelegate以及MainViewController类放置的组
CordovaLib组Cordova的核心类、JS,Native之间通信、整体控制类放置的组


Cordova本体JS与Native通信类

JS侧:

function(全局函数,JS加载的时候被执行)                
cordova(基本模块,所有的JS模块在这里面定义)

exec(JS和Native的窗口)                            
Channel(pub-sub定义、document/window#EventListener定义)
pluginloader(插件加载模块)                                    

Native侧:


CDVCommandQueue(插件API队列)    
CDViewController(全体控制类)
CDVCommandDelegateImpl(API控制类)                
CDVPlugin(所有的插件的父类)




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章