深挖一:移动端混合开发之hybrid

一、序言

滚滚长江东逝水,奔流到海不复回。
不要问我为为啥要废这么一句话,其实还是感叹前端发展的迅猛,很多技术和工具都是一闪而逝。如长江之水一样,转瞬即逝。
移动端开发的方式就是如此:
从2010年后的安卓和ios活了之后,移动端app开发的程序员可谓是如过江之鲫,源源不绝。
每年从培训班出来的程序员多达几万。笔者当时还想去参加ios培训呢。
然而过了几年后,考虑到开发成本、维护成本等各方面因素。分端开发已经越来越被当做一个开发效率的瓶颈。
现在让我看看解决这类问题的历程吧。

二、混合框架的两种模式

  1. hybrid :运行时联系沙盒。
  2. native : 编译时原生ui。
    今天主要是讲解hybrid的发展历程。而native会在下期跟大家见面。

三、hybrid

首先大家要明白deepLink的概念,不懂的推荐去看一篇文章链接:
点我去看deepLink
deepLink主要有url schema 和Universal Links 两种。本文准备深层次去讲解下 url schema的工作原理。
给出一个url schema的样例。

  1. dinglei://
  2. dinglei://getUserInfo

是不是看起来很眼熟,对了url schema本身就是一种协议,而且其工作原理和http的ajax还有些类似,上个别人的图。

ajax工作原理。

我们可以看到ajax的url一改变,就会被浏览器所监测到,然后发送给服务器。这一过程会开启一个线程。当服务器完成相应和返回数据后,线程会开始把回调压入到宏任务中,等待执行。

Attention Please!!!

如果说url schema 本身也是一个 同种类型的处理方式,你会不会偷着乐。

原谅我再次盗图:


url shcema 配合沙盒的工作原理图

请读者先记住以下几点:

  1. url schema 是app自身注册到手机系统里面的。其配置方式是工程项目下的info.plist里面配置的。在安装完成后,就已经保存在手机系统的协议列表中了。
  2. 当浏览器挂起这个url schema的请求时,第一接收方式系统本身,不是盒子!!!!
  3. 默认的链接如 weixin:// 盒子的操作都是发送给手机系统,然后手机系统回去列表上查,查到了会去通知对应的盒子做处理,一般是直接打开盒子。如果需要做其他操作,需要传参。
  4. 回调,依然是盒子获取盒子本身webview的全局对象,进行执行。

好吧!让我先上第一部分的干货吧。如何通过url schema去跟native实现一些业务场景吧。

window.testUrlSchemaGlobal = window.testUrlSchemaGlobal || {};


// 建立链接  ios 和安卓不同
function doConnection (url) {
  console.log(url);
    if (window.$plt.isMatch('ios')) {
        window.location = url;
    } else {
      setUrl(url);
    }
};

// 建立 安卓的 链接
function setUrl(url) {
  const iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  iframe.setAttribute('src', url);
  const d = () => {
    setTimeout(() => {
      document.body.removeChild(iframe);
    }, 1000);
  };
  document.body.appendChild(iframe);
}

// 构造url
function getUrlByParams (params) {
  debugger
    var paramStr = '', url = 'scheme://';
    url += params.funcName + '?t=' + new Date().getTime(); //时间戳,防止url不起效
    if (params.callback) {
        url += '&callback=' + params.callback;
        delete params.callback;
    }
    if (params.param) {
        paramStr = typeof params.param == 'object' ? JSON.stringify(params.param) : params.param;
        url += '&param=' + encodeURIComponent(paramStr);
    }
    return url;
};

/**
 * 
 * @param {*} params 
 * funName 
 * callback   传递名称 存放到  全局对象 testUrlSchemaGlobal  共bridge 去调用
 */
function requestHybrid (params) {
    //生成唯一执行函数,执行后销毁
    var tt = (new Date().getTime());
    var t = 'hybrid_' + tt;
    var tmpFn;

    //处理有回调的情况
    if (params.callback) {
        tmpFn = params.callback;
        params.callback = t;
        window.testUrlSchemaGlobal[t] = function (data) {
            tmpFn(data);
            delete window.testUrlSchemaGlobal[t];
        }
    }
    // 直接连接
    doConnection(getUrlByParams(params));
};


//获取版本信息,约定APP的navigator.userAgent版本包含版本信息:scheme/xx.xx.xx
function  getHybridInfo() {
    var platform_version = {};
    var na = navigator.userAgent;
    var info = na.match(/scheme\/\d\.\d\.\d/);

    if (info && info[0]) {
        info = info[0].split('/');
        if (info && info.length == 2) {
            platform_version.platform = info[0];
            platform_version.version = info[1];
        }
    }
    return platform_version;
};
举个例子:
requestHybrid({funcName:"dinglei",param:{isWeb:false},callback(){ console.log('callback') }});

其流程是
1.生成链接 scheme://dinglei?t=1545898661620&param=%7B%22isWeb%22%3Afalse%7D
2.然后注册全局的callback时间撮到去全局对象 testUrlSchemaGlobal中。
3.iframe去建立链接,传递信息。
4.系统处理这个链接,并向盒子发送。
5.盒子去处理相关任务,完成后调用全局的callback。

但是肯定会有同学,疑惑每次都经过手机系统的调度中心,做个中间转换。不是很浪费资源吗。
回答是yes啦。

看到这里是不是有种豁然开朗的感觉,喜欢的同学给个赞,因为作为新人,您的点赞会是我持续写作的动力。
但是你以为已经结束了吗?


chaoxiao

这只是最原始的交互方式,换而言之,在hybrid的方式中,这种事最low的。也是最直接的。

先给大家介绍ios关于交互方式的发展流程。让大家有个直接的印象。

  • 1.有很多的app直接使用在webview的代理中通过拦截的方式与native进行交互,通常是通过拦截url scheme判断是否是我们需要拦截处理的url及其所对应的要处理的功能是什么。任意版本都支持。也即是我们上面所说的方案。
  • 2.iOS7之后出了JavaScriptCore.framework用于与JS交互,但是不支持iOS6,对于还需要支持iOS6的app,就不能考虑这个了。若需要了解,看最后的推荐阅读。
  • 3.WebViewJavascriptBridge开源库使用,本质上,它也是通过webview的代理拦截scheme,然后注入相应的JS。
    我们再来看看第三种交互方式。jsbridge。相信用过微信或者支付宝早起版本进行开发的同学。应该对这个东西很眼熟。让我们来看看它是怎么使用的。

首先我们回忆下我们上面的链接方式,是每次都会建立一次链接,给手机系统的调度中心,手机调度中心传给app盒子,盒子来决定做什么事情。这样是耗性能的。这是上面大致的情况。
让我思考下,什么时候是一定需要传给手机调度中心的?

很简单在盒子外的h5中打开链接的时候,是希望进行跳转到某个页面,这个时候因为不在沙盒内,是必须要传递给手机调度中心的。而页面本身在盒子里面的时候,那直接传递给沙盒不是更好点?

jsbridge就是干这件事情的,它除了第一次建立链接是传递给手机的调度中心,后面都是功过bridge直接监听url schema的。
直接上代码来讲解:

  • 第一步建立链接

function setupWebViewJavascriptBridge(callback) {
    //  WebViewJavascriptBridge   传递信息
    if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
     // 建立回调 等同于 全局回调。
    if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
    window.WVJBCallbacks = [callback];
  // 建立链接
    var WVJBIframe = document.createElement('iframe');
    WVJBIframe.style.display = 'none';
    WVJBIframe.src = 'scheme://__BRIDGE_LOADED__';
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
  • 第二步注册方法

WebViewJavascriptBridge.registerHandler(handlerName,
      function(data, callback) {
                //alert('handlerName callback' + data);
                responseCallback(data),
                callback && callback({
                  errorCode: "0",
                   errorMessage: "成功"
                })
})
  • 第三步使用

WebViewJavascriptBridge.callHandler(path, params);

因为水平有限,暂时如此。后面等研究够了,会继续更新。

参考

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容