hybrid通信原理--jockey源码解析广东高防服务器租用佛山稳定竞价服务器大带宽
需要服务器咨询以下联系方式
联系人:銳輝(香港)科技 敏敏
扣扣:3007425289/2853898501
电话:18316411879
稳定24小时售后 不限流量cn2带宽
第二台机器半价 先到先得 新机柜 上完截止 没有抢到等新的机柜
香港免备案机器那款才是最好,香港机房现全新配置上线,机器硬件可升级,g口cn2线路独独享带宽,国内延迟低,可提升防御,死扛流量攻击,机房策略可针对各种攻击方式,公司售后7*24小时技术在线处理问题。为您的机器保驾护航。
虚拟主机就是集体宿舍 一人脚臭全屋熏天
虚拟服务器就是小户型 麻雀虽小五脏俱全
独立服务器那就是单元房了 我的地盘我做主
我们机房运营商就是开发商物业管理 欢迎您入住
服务承诺
1.提供一级电信运营商的资源。
2.可按用户要求进行ip地址指向的最优分配。
3.提供7×24小时技术支持服务。
4.如遇计划性中断,提前24小时通知。
5.根据客户需求提供流量监测,分析报告。
你找卖家,卖家再找公司,公司再找机房......
等处理好已经不是服务问题了,
而是时间,玩家流失的问题了,
这就和选老婆一样,老婆不会做家务也没用,
所以选服务器一定要选有售后保障的。
锐辉网络科技24小时在线售后!
您选择锐辉就不怕没人处理问题了!
1.1 什么是hybrid通信
本文讲的hybrid通信指的是:在hybrid框架中,h5与native之间的交互。
交互包括两部分:
h5访问native,应用场景有设置导航栏,调用native组件等;
native访问h5,应用场景有h5分享,执行h5回调等;
1.2 h5与native交互实现原理
交互分成两中场景:
h5访问native
h5发送scheme请求,如jockcy://xxx?param=xx;
native有一个进程监听webview中所有请求,解析url,然后处理事件;
native访问h5
h5注册全局方法,挂载window对象上;
native直接调用webview下的window对象上的方法;
想要实现上面功能,jockey.js 是一个很好的选择,封装了h5与native之间的交互,精简适用,接下来会逐步解析jockey源码。
另外,若对前文提到hybrid,webview,scheme等技术想更多了解,移步同事xiaobu的文章:hybrid简单了解
2. jockey源码解析
2.1 jockey实现了哪些功能
jockey暴露了一个jockey对象,挂载在window上,主要功能如下:
检测当前运行环境是否在webview中;
h5发送消息给native,jockey.send();
h5注册全局方法,jockey.on();
native响应h5的回调函数,jockey.triggercallback();
native主动调用h5的全局方法,jockey.trigger();
2.2 初始化变量,检测运行环境
// 通过iife方式,封装jockey
(function (){
var host = window.location.host; // 发送消息带的参数,native用来判断scheme请求的有效性
var iframedispatcher = {}; // 实现非native端处理
var nativedispatcher = {}; // 实现native端处理
var jockey = {}; // 定义jockey对象
var i = 0,
ios = false
idevice = ['ipad', 'iphone', 'ipod'];
for (; i < idevice.length; i++) {
if (navigator.platform.indexof(idevice) >= 0) {
ios = true;
break;
}
}
var uiwebview= /(iphone|ipod|ipad).*applewebkit(?!.*safari)/i.test(navigator.useragent);
var isandroid= navigator.useragent.tolowercase().indexof("android") > -1;
if ((ios && uiwebview) || isandroid) {
// 如果是native中运行,则可以通过nativedispatcher实现交互
jockey.dispatchers.push(nativedispatcher);
}
// 如果不是在native运行,默认通过postmessage实现异步回调;
// 这里的作用,主要为了让hybrid页面非app环境,调用jockey也能正常返回。
jockey.dispatchers.push(iframedispatcher);
window.addeventlistener("message", $.proxy(jockey.onmessagerecieved, jockey), false);
window.jockey = jockey;
})();
这是jockey的主流程代码,主要做了3件事,
通过iife方式,封装jockey;
初始化jockey、nativedispatcher等对象;
检测当前运行环境,根据不同环境做对应处理;
2.3 h5发送消息给native
var jockey = {
listeners: {}, // 监听事件
dispatchers: [], // 具体处理模式,两种环境
messagecount: 0, // 消息数量
on: function () {}, // h5注册全局方法
trigger: function () {}, // native主动调用h5的全局方法
triggercallback: function () {}, // native响应h5的回调方法
send: function(type, payload, complete) { // h5发送消息给native
// 参数兼容处理
if (payload instanceof function) {
complete = payload;
payload = null;
}
payload = payload || {};
complete = complete || function() {};
// 创建消息格式对象
var envelope = this.createenvelope(this.messagecount, type, payload);
// 实际处理
this.dispatchers.foreach(function(dispatcher) {
dispatcher.send(envelope, complete);
});
// 消息数量自增
this.messagecount += 1;
},
createenvelope: function(id, type, payload) {
return {
id: id,
type: type,
host: host,
payload: payload
};
}
从上面源码,可以看出jockey这个对象很简单,实现了四个方法及一些变量定义。
其中h5调用native,native响应回调函数,这两个方法是一次完整的交互;
h5注册全局函数,native主动调用全局方法,这两个方法是一次完整的交互;
我们继续看下dispatcher的实现,如何通过scheme url 发送消息:
var nativedispatcher = {
callbacks: {}, // 回调对象
send: function (envelope, complete) {
this.dispatchmessage("event", envelope, complete);
},
dispatchmessage: function(type, envelope, complete) {
var dispatcher = this;
// 发送前,先把回调事件存起来
this.callbacks[envelope.id] = function() {
complete();
delete dispatcher.callbacks[envelope.id];
};
// scheme请求
var src = "jockey://" + type + "/" + envelope.id + "?" + encodeuricomponent(json.stringify(envelope));
// 通过添加iframe,发送消息
var iframe = document.createelement("iframe");
iframe.setattribute("src", src);
document.documentelement.appendchild(iframe);
iframe.parentnode.removechild(iframe);
iframe = null;
}
ok,到了这里,h5已经把scheme请求发出去了,回调函数也存储在内存中了;等待native监听webview中的请求,解析执行完后,调用h5的triggercallback,h5就可以执行响应回调函数了。
2.4 native响应回调函数
当native执行完h5请求事件后,需要告诉h5,调用jockey.triggercallback
var jockey = {
triggercallback: function(id) {
this.dispatchers.foreach(function(dispatcher) {
dispatcher.triggercallback(id);
});
},
}
var nativedispatcher = {
// 实际执行响应函数
triggercallback: function(id) {
var dispatcher = this;
// settimeout是为了避免app的运行卡顿
settimeout(function() {
dispatcher.callbacks[id]();
}, 0);
到这里,就完成了h5调用native,native响应回调的完整交互。
2.5 h5注册全局事件
var jockey = {
listeners: {}, // 数组对象存储不同类型监听事件(即h5的全局事件)
on: function(type, fn) {
if (!this.listeners.hasownproperty(type) || !this.listeners[type] instanceof array) {
this.listeners[type] = [];
}
this.listeners[type].push(fn);
2.6 native调用h5全局事件
var jockey = {
// native调用h5,通过fifo队列方式,一个个执行该类型的h5监听事件
trigger: function(type, messageid, json) {
var self = this;
var listenerlist = this.listeners[type] || [];
var executedcount = 0;
// 完成函数,需告诉native已完成回调
var complete = function() {
executedcount += 1;
if (executedcount >= listenerlist.length) {
self.dispatchers.foreach(function(dispatcher) {
dispatcher.sendcallback(messageid);
});
}
};
for (var index = 0; index < listenerlist.length; index++) {
var listener = listenerlist[index];
// 如果h5方法是异步函数,需要执行完异步函数后手动调用complete方法
// 当所有事件都执行完后,h5在通知native执行完成
if (listener.length <= 1) { // 回调函数参数小于两个,是同步
listener(json);
complete();
} else { // 回调函数参数有两个,是异步函数
listener(json, complete);
var nativedispatcher = {
sendcallback: function(messageid) {
var envelope = jockey.createenvelope(messageid);
// 告诉native,回调函数已经完成。应用场景:如h5分享功能
this.dispatchmessage("callback", envelope, function() {});
},