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

       之前分析了与平台无关的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);







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值