7 (phonegap源码分析) 平台相关模块和初始化(platform)

来源:互联网 发布:java io readline 编辑:程序博客网 时间:2024/06/06 23:57

       之前分析了与平台无关的common模块,这节来分析下与平台相关的platform模块和phonegap的初始化。

define("myphonegap/platform", function(require, exports, module) {        module.exports = {id: "android",initialize:function() { }clobbers: { //需要覆盖的属性navigator: {children: {app:{path: "myphonegap/plugin/android/app"}}},   //省略open: {path: "myphonegap/plugin/InAppBrowser"}},merges: { //需要合并的属性device: {path: 'myphonegap/plugin/android/device'},navigator: {children: {notification: {path: 'myphonegap/plugin/android/notification'}}}}}};


        该模块是与平台相关的,现在分析的是android平台,所以这部分代码与android平台相关。platform对象实例提供了一个initialize方法用来执行平台初始化代码,id表示不同平台,clobbersmergescommon下的属性作用相同,都是一个字面量对象,作为builder模块函数的参数用来生成相应模块对象;二者区别在于clobbers是属性覆盖,merges是属性合并。

        platformcommon类似,因为与平台相关,这里暂时不测试了。

        当所有define语句执行完成也就是模块定义之后,开始模块初始化或实例化。先请求主模块对象,将主模块对象添加到全局执行环境;之后是一个自执行的匿名函数,context是形参,window是实参。

window.myphonegap = require(‘myphonegap’);(function (context) {if (context.navigator) {}var channel = require("myphonegap/channel"),_self = {boot: function () {},    [ channel.onNativeReady,channel.onDOMContentLoaded ]);}};channel.onNativeReady.subscribe(_self.boot);if (window._nativeReady) {channel.onNativeReady.fire();}}(window));

        第一个if语句中的代码是对navigator这个变量做处理,让window下的navigator中的所有属性变成了它的原型中的属性。到底有什么意义,不太明白,看代码注释,clobber这个单词没看懂什么意思。

// Replace navigator before any modules are required(), to ensure it happens as soon as possible.    // We replace it so that properties that can't be clobbered can instead be overridden.if (context.navigator) {var CordovaNavigator = function() {};CordovaNavigator.prototype = context.navigator;context.navigator = new CordovaNavigator();}

        看下面的两个对象的定义,一个是channel通道模块,看来下面的代码涉及到事件订阅了。_self对象中只有一个函数对象boot, boot函数是初始化引导函数,里面执行的是channel.join函数,参数为一个匿名函数和两个通道对象组成的数组。Join函数代码比较费劲,它的第二个参数是个通道对象数组,当所有通道事件触发一次之后,执行第一个参数传递过来的函数。

var channel = require("myphonegap/channel"),_self = {boot: function () {channel.join(function() {}, [ channel.onNativeReady,channel.onDOMContentLoaded ]);}};

        然后再看看join函数的第一个参数,匿名函数中的内容。先请求buildercommonplatform三个模块对象,然后根据这三个对象构建了其它的模块对象。之后执行平台初始化,触发onMyphonegapReady事件;最后一个语句,将onDeviceReady事件的触发,绑定在 channel.deviceReadyChannelsArray中的所有事件触发之后。

 function() {var builder = require('myphonegap/builder'),base = require('myphonegap/common'),platform = require('myphonegap/platform'); builder.buildIntoButDoNotClobber(base.defaults, context);builder.buildIntoAndClobber(base.clobbers, context);builder.buildIntoAndMerge(base.merges, context);builder.buildIntoButDoNotClobber(platform.defaults, context);builder.buildIntoAndClobber(platform.clobbers, context);builder.buildIntoAndMerge(platform.merges, context);                        //调用平台初始化 platform.initialize();                        //触发onMyphonegapReady通道事件 channel.onMyphonegapReady.fire();// deviceReadyChannelsArray上的所有事件被触发之后,触发第一个参数传入的匿名函数       channel.join(function() {require('myphonegap').fireDocumentEvent('deviceready');}, channel.deviceReadyChannelsArray);}

        其实立即上面这段代码的关键是立即join这个函数,这个函数是channel提供的。代码如下:

join: function(h, c) {            var len = c.length,                i = len,                f = function() {                    if (!(--i)) h();                };            for (var j=0; j<len; j++) {                if (c[j].state === 0) {                    throw Error('Can only use join with sticky channels.');                }                c[j].subscribe(f);            }            if (!len) h();        }

        理解这个函数的关键是如何看待f这个对象,给f赋值的是一个函数表达式,函数表达式是不同于函数声明的,当然函数声明是无法直接对变量进行赋值的。这个函数表达式中的变量i此时就是这个函数对象的一个属性了,而且它的初始值就是数组c的长度;函数h就是对象f的另一个属性;当f函数被调用的时候i1f函数被提交到了channel通道上,也就是说c是个通道数组,当这个通道数组的所有事件都被触发之后,i才变为0,此时h函数才被执行。

        对比下JAVA语言实习类似f函数的功能:fh都为接口,通道事件订阅是以接口为参数。

  interface InterfaceF{  public void f();  }  interface InterfaceH{  public void h();  }  ClassF implements  InterfaceF{  private int i = 0;  private InterfaceH  interfaceH;  ClassF(int i  , InterfacH interfacH){  this.i = i;  this.interfacH = interfacH;  }  Public void f(){  if(--i == 0) interfaceH.h();  }  }InterfaceF instanceF = new ClassF(c.length, instanceH);







原创粉丝点击