Hybrid设计与实现

背景及概述

随着移动浪潮的兴起,各类APP层出不穷,极速的业务扩展提高了团队对开发效率的要求,这个时候使用IOS&Andriod开发一个APP彷佛成本有点太高了,而H5的低成本、高效率、跨平台等特性立刻被利用起来造成了一种新的开发模式:Hybrid APP。
做为一种混合开发的模式,Hybrid APP底层依赖于Native提供的容器(UIWebview),上层使用Html&Css&JS作业务开发,底层透明化、上层多多样化,这种场景很是有利于前端介入,很是适合业务快速迭代,因而Hybrid火啦。
Hybrid App主要以JS+Native二者相互调用为主,从开发层面实现“一次开发,多处运行”的机制,成为真正适合跨平台的开发。Hybrid App兼具了Native App良好用户体验的优点,也兼具了Web App使用HTML5跨平台开发低成本的优点。javascript

目前已经有众多Hybrid App开发成功应用,好比美团、爱奇艺、微信等知名移动应用,都是采用Hybrid App开发模式。css

为何要引入hybrid开发html

Native应对急速业务需求,APP迭代加快,频繁的发版已难以应付
Android渠道众多,apple store审核周期长
纯native开发效率低,开发维护成本高
不能及时修复bug,不能动态发版
相对于其余动态发布技术,技术研发成本较低,使用语言更普遍,社区资源更丰富

Hybrid开发优劣势

三种开发模式对比前端

Native App 即 原生App开发

<font color=#A52A2A size=3 face="黑体">优势</font>java

(1)打造完美的用户体验
(2)性能稳定
(3)操做速度快,上手流畅
(4)访问本地资源(通信录,相册)
(5)设计出色的动效,转场,
(6)拥有系统级别的贴心通知或提醒
(7)用户留存率高

<font color=#A52A2A size=3 face=“黑体”>缺点</font>android

(1)分发成本高(不一样平台有不一样的开发语言和界面适配)
(2)维护成本高(例如一款App已更新至V5版本,但仍有用户在使用V2, V3,V4版本,须要更多的开发人员维护以前的版本)
(3)更新缓慢,根据不一样平台,提交–审核–上线 等等不一样的流程,须要通过的流程较复杂。

Web App 即 网页App开发

  • 特色(html css js)
  • 优点 (发版彻底自控随时更新开发成本小时间快)
  • 劣势(性能差弱网络无网络条件下体验差)Web App其实就是写好的一套长得像App UI界面的可以自适应的网页加壳。本质套webview壳子打包成App,走的都是web页面(html css js),这种方式对于作过Web开发的开说很是轻松就能够作出一个属于本身的App,由于自己来讲用的就是Web的东西,因此有很是好的跨平台的特性能够在任意平台运行,包括发版这方面web能够随时部署因此不须要发版,web页面嵌入webview开发起来速度很是快,一我的就能够轻松搞定,对有展现类需求的项目来讲采用这种方式是最适合的,可是若是要实现的功能比较复杂的话就显得力不从心了。
    相比Native App,Web App体验中受限于网络环境和渲染性能。
  1. 网络环境,渲染性能
    Web APP对网络环境的依赖性较大,由于Web APP中的H5页面,当用户使用时,去服务器请求显示页面。若是此时用户恰巧遇到网速慢,网络不稳定等其余环境时,用户请求页面的效率大打折扣,在用户使 用中会出现不流畅,断断续续的不良感觉。同时,H5技术自身渲染性能较弱:对复杂的图形样式,多样的动效,自定义字体等的支持性不强。

所以,基于网络环境和渲染性能的影响,在设计H5页面时,应注意如下几点:ios

1.简化不重要的动画/动效
2.简化复杂的图形文字样式
3.减小页面渲染的频率和次数

Hybrid App 即 混合型App开发

<font color=#A52A2A size=3 face="黑体">优势</font>web

一、跨平台
二、开发周期短、成本低
三、用户体验良好
四、能够即时修复bug、动态发版

<font color=#A52A2A size=3 face=“黑体”>缺点</font>
一、虽说你能够专一在界面以及交互开发上了,可是这页会成为一个缺点,好比说要仿造一个iOS的默认设置界面,就须要大量的html以及css代码了,并且效果不必定和iPhone上面的界面同样好;
二、正由于这是跨平台的开发,因此仍是这句话:兼容是前端的痛。了解过在Android机器上面的Web开发就知道这个痛了。好比前些年在Android设备上面写圆角,border-radius:10px,在Android的设备上面会出现毛边。
三、便于调试实际上是在Web界面层的。可是实际上作Hybrid App开发的时候,你会遇到需求,进入手机的底层请求,作某些处理。好比说若是该应用有Push Notification服务的话,你就须要到底层,获取Push Notification发生时的数据,以及作相应的交互处理。固然相似PhoneGap这类框架,已经有很好的插件机制去帮助你解决相似的问题,固然还有Game Center之类的插件,具体的话能够到Github去关注PhoneGap官方的帐户,资源很是丰富ajax

前端与native分工

在作Hybrid架构设计以前须要分清Native与前端的界限,首先Native提供的是一宿主环境,要合理的利用Native提供的能力,要实现通用的Hybrid平台架构,站在前端视角,我认为须要考虑如下核心设计问题。canvas

交互设计

Hybrid架构设计第一个要考虑的问题是如何设计与前端的交互,若是这块设计的很差会对后续开发、前端框架维护形成深远的影响,而且这种影响每每是不可逆的,因此这里须要前端与Native好好配合,提供通用的接口,好比:

① NativeUI组件,header组件、消息类组件

② 通信录、系统、设备信息读取接口

③ H5与Native的互相跳转,好比H5如何跳到一个Native页面,H5如何新开Webview作动画跳到另外一个H5页面

资源访问机制

Native首先须要考虑如何访问H5资源,作到既能以file的方式访问Native内部资源,又能使用url的方式访问线上资源;须要提供前端资源增量替换机制,以摆脱APP迭代发版问题,避免用户升级APP。这里就会涉及到静态资源在APP中的存放策略,更新策略的设计,复杂的话还会涉及到服务器端的支持。

帐号信息设计

帐号系统是重要而且没法避免的,Native须要设计良好安全的身份验证机制,保证这块对业务开发者足够透明,打通帐户信息。

Hybrid开发调试

功能设计完并非结束,Native与前端须要商量出一套可开发调试的模型,否则不少业务开发的工做将难以继续,这个不少文章已经接受过了,本文不赘述。

至于Native还会关注的一些通信设计、并发设计、异常处理、日志监控以及安全模块由于不是我涉及的领域便不予关注了(事实上是想关注不得其门),而前端要作的事情就是封装Native提供的各类能力,总体架构是这样的

Hybrid交互设计

Hybrid交互有两种:
一、native主动调用前端js方法主动与前端通讯
二、H5主动与native通讯是经过url schema方式进行的,首先要和native约定好通讯的schema 如:wubacst 而后根据Android和iOS不一样的通讯方式来分别约定 其中Android是在通讯以前先建立一个iframe经过iframe把拼接好的url请求发送到native或者经过拦截prompt中的消息来和前端通讯 iOS使用了iOS8以上的wkwebview中的messageHandlers的postMessage方法直接把url请求发送到native native接收到前端发送的请求解析以后经过回调函数来通知前端

二者通讯的桥梁都是webview

Hybrid交互原理

这里写图片描述

4.1.一、WKWebView+WKScriptMessageHandler实现JS与OC之间互相通讯

iOS 基于WebKit框架的中的WKWebView+WKScriptMessageHandler实现JS与OC之间互相通讯。
总体交互过程分为三步:
第一:经过- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name,搭建JS调用OC的桥梁,注册供JS调用的方法name;
第二:JS在调用OC注册方法只须要:window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
第三:客户端在WKScriptMessageHandler代理方法里收到JS的调用,经过解析处理,并按照事先与FE约定好的的协议作方法的映射,从而达到JS事件的响应。

4.1.二、UIWebview的javaScriptcore方式

将 UIWebViewDelegate 与 UIWebView 拆分红了14类与3个协议,包含该更细节功能的实现

  • (void)evaluateJavaScript:(NSString )javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError _Nullable error))completionHandler

WKWebView :

一、在性能、稳定性、功能方面有很大提高
二、更多的支持 HTML5 的特性
三、官方宣称的高达60fps的滚动刷新率以及内置手势
四、Safari 相同的 JavaScript 引擎

Hybrid通讯机制

4.2.一、总体设计

这里写图片描述

4.2.二、native与js通讯流程

这里写图片描述

4.2.三、js与native交互流程

这里写图片描述

相似于JOSNP跨域原理
APP在安装以后会注册私有协议到OS,浏览器自身不能识别的协议时,会将连接抛给OS,转为APP处理
好比itunes://开头的连接是Apple Store的私有协议,支付宝的私有协议alipay://,腾讯的tencent://等等
固定协议:webview.loadUrl("javascript: alert('hello world')");

交互协议设计

API式交互

调用native API接口方式和咱们请求服务端的ajax方式相似,都是前端主动去发送一个请求,被接收处理后返回回调
这里写图片描述

交互数据格式约定

混合开发中交互种类繁多,如何作到通用
以58同城车商通app为例:
页面跳转类型

wubacst://jumppage/...?query=…

native组件处理类型

wubacst://handlejs/...?query=…

前端协议封装

前面提到过,Android和iOS对于前端的交互是有区别的,虽然都是采用URL拦截的方式,可是具体的方式是不同的;iOS采用WKwebview中的messageHandlers方法,而Android采用相似ajax同样的请求;可是对于业务放来讲,在和native通讯时是不区分端的,这就须要封装一个交互协议的API来提供给业务方,在协议API中来区分处理Android和iOS的交互;

处理源码以下:

//区分处理Android和iOS
  _nativeBridge: function(param) {
        "android" == this.os ? this._andr4Native(param) : 
        "ios" == this.os ? this._ios4Native(param) : "ipad" == this.os && this._ios4Native(param)
    },

Android客户端处理

_createIframe: function() {
        var iFrame;
        return iFrame = document.createElement("iframe"),
            iFrame.setAttribute("style", "display:none;"),
            iFrame.setAttribute("height", "0px"),
            iFrame.setAttribute("width", "0px"),
            iFrame.setAttribute("frameborder", "0"),
            iFrame
    }
 //开始是使用iframe和Android客户端通讯 后来改为了prompt   
 _andr4Native: function(param) {
        var host = param.host;
        var path = param.path;
        var query = param.query;
        query = JSON.stringify(query)
        //3.5.0以上版本Android端都走新的拦截方式
        var url = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query);
        if(this._versionCompare(this._getVersion(),'3.5.0')){
            window.prompt(url)
        }else{
            if (!this.domReady)
            return void this.actionPreQueue.push(param);
        this.andrFrame = this._createIframe(),
            this.andrFrame.src = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query),
            document.body.appendChild(this.andrFrame),
            this.andrFrame = null
        }
        
    }

iOS客户端处理

//messageHandlers上绑定的WBcheshangtong对象是和iOS约定好的
_ios4Native: function(param) {
        var host = param.host;
        var path = param.path;
        var query = param.query;
        query = JSON.stringify(query);
        var url = "wubacst://" + host + "/" + path + "?query=" + encodeURIComponent(query);
        if (window.webkit) {
            try {
                window.webkit.messageHandlers.WBcheshangtong.postMessage(url);
            } 
        }
    }

处理好底层交互以后,在根据业务的不一样,前端封装一些通用的协议,如:
这里写图片描述

整个通讯协议API以下:

app58.prototype = {
     init: function() {},
 _nativeBridge: function(param){},
_ios4Native: function(param){},
_andr4Native: function(param){},
_createIframe: function(){},
loadPage: function(path, url, jumpParameter,title,titleColor,isDestoryBeforePage){}
...
}
var WBAPP = new app58(window.app_config || null)

问题总结

iOS cookie丢失问题

目前来讲WKwebview还不是那么稳定,常常会出现前端cookie丢失问题,一下是本人在开发过程当中解决问题的一个过程:
这里写图片描述
最终是用hookAjax来实现的
hookAjax的原理就是拦截全部的网络请求,代理send方法实现本身的目的
这里写图片描述
有兴趣的能够去看看hookajax 这里就再也不详细讲解了

Android通讯协议重复提交

因为Android使用的是iframe发送请求和Android客户端进行交互的,在前端使用canvas时,iframe重复执行,致使前端重复提交协议,目前换成了prompt交互;在开发过程当中有遇到这种问题的小伙伴,欢迎留言。

相关文章
相关标签/搜索