开发移动App主要有三种模式:Native、 Hybrid 和 Web App。javascript
须要注意的一点是在选择开发模式的时候,要根据你的项目类型(图片类?视频类?新闻类?等),产品业务和人员技术储备等作权衡。css
Hybrid开发模式就是既有Native开发也有Web app的开发。那咱们怎么去肯定App中某个功能模块使用Native仍是Web开发?它们之间若是须要接口通讯又该如何去实现呢?又该如何更好的去维护Hybrid App产品呢?html
当咱们选择用Hybrid模式开发App时,应先熟悉项目整个框架和App各个模块。而后将通用的,对性能要求不是那么高的App界面可抽出来做为web界面开发,Native直接调用。通常Hybrid App开发,App界面之间的跳转关系由Native实现并完成,web界面主要做为内容填充到Android和iOS的浏览器控件中。拉手网以前Android客户端就是采用这种模式,Native搭一个App框架壳,里面展现内容和网络请求所有由web实现。因为客户端浏览器控件版本不一样,web界面加载,渲染和缓存机制等缘由,这种模式开发的App总体在图文比较多的状况下体验就不太好,甚至可能会出现意想不到的奇葩问题。 建议图文列表,涉及到视频等多并发和界面元素比较负责或具备很强的动画特效的状况优先考虑Native开发。 这方面在Android尤为有必要,Android 4.4以前的浏览器控件WebView基于缺省的WebKit内核,它不一样于Chromium所使用的Webkit内核;而在4.4以后(包括4.4)的WebView的实现被替换成Chromium WebKit内核。当咱们想让App尽量的在低版本也能运行良好时,就须要不断作兼容性开发和测试了,除非本身在App里面打包编译最新WebView源码,相似开发一个浏览器。java
Android和iOS都提供了API直接调用:android
webview.loadUrl("javascript:functionName(\"" + argument + "\")");
别忘了设置 webview.getSettings().setJavaScriptEnabled(true); web
[webView stringByEvaluatingJavaScriptFromString:@"alert('hello world!')"];
Android实现js调用native方法通常是先编写供js调用的类,而后经过添加javascripteInterface的方法,如api
webView.addJavascriptInterface(pandoInterface, "pando");
将java对象pandoInterface生成js对象pando,而后直接window.pando就能够调用pandoInterface对象里面的方法。须要注意的是供js调用的pandoInterface对象里面的java方法需手动加上@JavascriptInterface注解,这个是Google为解决安全问题引入的。浏览器
iOS实现js调用Native方法相对繁琐一点。主要是iOS原生并无提供js直接调用native的方式,只能经过UIWebView相关的UIWebViewDelegate协议的方法来作拦截,并在这个方法中,根据url的协议或特征字符串来作调用方法或触发事件等工做。当js须要调用Native方法时,js建立一个隐藏的iframe设置或改变其src就会触发Native拦截url事件。缓存
如安全
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *url = [request URL]; if ([[url scheme] isEqualToString:@"someFunction") { //调用原生方法 return NO; } else { return YES; } }
不知道你们发现没有,以上两种方法都只是实现了js调用Native方法,可是都没有实现js函数回调,将Native方法返回结果传递给js。
微信开放了不少jsApi接口,供你们直接调用微信Native的功能。经过jsApi接口和文档咱们会发现里面实现了Native方法执行结果回调给js。这种Hybrid App开发模式很好的利用了Native高性能,多并发的优点,将网络请求,扫码等复杂的逻辑或者web不可能实现的功能由Native完成,而web只是作了界面显示效果。将微信Android安装包解压以后,在assets/jsapi目录下有个80多kb的wxjs.js文件,里面实现了微信jsApi逻辑jsbridge。下面主要简单介绍一下这种jsbridge实现原理。
jsbridge核心难点在于如何在Native方法执行完以后将返回接口给js,而且让js能理解传过来的参数所表达的意思。针对这,咱们能够在js调用Native方法之间,将js一次调用Native的惟一标示符identifier和指望Native调用完后执行的回调函数存储在Map里面,将identifier和其余参数传递给Native,native执行完成后,将identifier和执行结果做为参数调用js函数,在js函数里面解析参数,获得identifier,而后在Map里查询对应的回调函数,将native执行结果做为参数传递进去调用。有点绕,可是巧妙的利用消息传递机制,实现js调用Native进行回调函数调用,同理,Native调用js函数将返回结果给Native调用也是能够的。
Android在实现jsbridge时,早期方法也是须要iOS那样,先给web界面建立iframe,而后经过js改变iframe src,Native方法经过shouldOverrideUrlLoading(WebView view, String url)拦截url处理。可是在Android 4.2.2系统上,这个方法在iframe src改变是,是不会触发的。目前建议你们经过拦截js alert弹框作处理。
@Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { LogUtils.i("url:" + url+"\n message:" + message); try { String msg = URLDecoder.decode(message, "utf-8"); if (msg.startsWith(BridgeUtil.PANDO_RETURN_DATA)) { // 若是是返回数据 handlerReturnData(message); result.cancel(); return true; } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return super.onJsAlert(view, url, message, result); }
注意,onJsAlert方法拦截作处理后必定要result.cancel();否则web界面就会出现点击没反应的状况。
Hybrid App涉及到html、css和js等web资源文件,当web和Native之间有相互调用时,二者之间任何一方接口变更都会致使App出现bug。
Q:
最近想本身写个android的hybrid app,看了下大多推荐的是PhoneGap,不知道他的运行效率怎么样,若是以原生为重的话,适不适合用PhoneGap?
A:
我来讲说吧,其实就是mui开发最快,这是我本身实践的结果,ionic我没用,但是cordova我用过,由于国内没多少人分享经验,因此坑不少。
你作一个带扫码,摇一摇,地理位置追踪,消息推送的app,这些基础功能mui基本不用研究拿来就能用。cordova光是研究插件集成和使用就得花3天时间,中间还会有不少坑。(这个已经有半成品)
可是,cordova对于你作一个需求比较奇特的app来讲很好,由于他的插件库全。mui对这个支持比较弱。(这个试了一周后放弃)
话又说回来,若是那么奇特需求的app在技术选型上为何不选原生?若是非得用hybird本身用webview作就是了。学cordova的时间够把如何原生调用js和js调用原生弄明白10次了。如今我就是这么作的。
A:
若是对原生的部分功能要求较高的话,不推荐使用PhoneGap,虽然说如今已经很成熟,可是若是涉及到原生功能仍是不好的,我以前体验过。。
---------------------------分------------割-------------------------------------
以上内容摘自
https://www.tuicool.com/articles/riE3Yn
感谢大神们的实践总结~