0
点赞
收藏
分享

微信扫一扫

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习

前言

我们大前端团队内部 📖每周一练 的知识复习计划还在继续,本周主题是 《Hybird APP 混合应用专题》 ,这期内容比较多,篇幅也相对较长,每个知识点内容也比较多。


注:本文整理资料来源网络,有些图片/段落找不到原文出处,如有侵权,联系删除。

一、什么是 Hybird App,与 Native App 及 Web App 有什么区别

参考文章:


  1. [《Web App Hybrid App和 Native App的区别》] (http://www.ionic.wang/article-index-id-58.html)

  2. [《Hybrid APP基础篇(二) -> Native、Hybrid、React Native、Web App方案的分析比较》]

1.1 主流应用类型

随着现在移动互联网的快速发展,市面上目前主流移动应用程序主要分三类:Web AppNative AppHybrid App

三者大致关系如下:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_javascript

1.2 Web App

Web App,即移动端网站,一般指的是基于 Web 的应用,基于浏览器运行无需下载安装,基本上可以说是触屏版的网页应用。这类应用基本上是一个网页或一系列网页,旨在在移动屏幕上工作。

Web 网站一般分为两种:


  1. MPA(Multi-page Application)

  2. SPA(Single-page Application)

一般的 Web App 是指 SPA 形式开发的网站。

优点:

  • 开发和维护成本低,可以跨平台,调试方便;

前端人员开发的代码,可应用于各大主流浏览器(特殊情况可以代码进行下兼容),没有新的学习成本,而且可以直接在浏览器中调试。

  • 更新最为快速;

由于web app资源是直接部署在服务器端的,所以只需替换服务器端文件,用户访问是就已经更新了(当然需要解决一些缓存问题)。

  • 无需安装App,不会占用手机内存;

通过浏览器即可访问,无需安装,用户使用成本更低。

缺点:

  • 性能低,用户体验差;

由于是直接通过的浏览器访问,所以无法使用原生的API,操作体验不好。

  • 依赖于网络,页面访问速度慢,耗费流量;

Web App每次访问都必须依赖网络,从服务端加载资源,当网速慢时访问速度很不理想,特别是在移动端,对网站性能优化要求比较高。

  • 功能受限,大量功能无法实现;

只能使用 HTML5 的一些特殊 API ,无法调用原生 API ,所以很多功能存在无法实现情况。

  • 临时性入口,用户留存率低;

这既是它的优点,也是缺点,优点是无需安装,确定是用完后有时候很难再找到,或者说很难专门为某个web app留存一个入口,导致用户很难再次使用。

1.3 Native App

Native APP 指的是原生程序,需要用户下载安装使用,一般依托于操作系统,有很强的交互,是一个完整的App,可拓展性强,能发布应用商店。

目前市面上主流的平台有:AndroidiOS

优点:


  • 直接依托于操作系统,用户体验好操作流畅性能稳定

  • 用户留存率高;

  • 功能最为强大,特别是在与系统交互中,几乎所有功能都能实现;

由于 Native APP 是直接依托于系统,所以可以直接调用官方提供的API,功能最为全面(比如本地资源操作,通知,动画等)。

缺点:

  • 开发和维护成本高,无法跨平台,需要各平台各自独立开发;

Android 上基于 Java 开发,iOS 上基 OCSwift 开发,相互之间独立,必须要有各自的开发人员。

  • 门槛较高,原生人员有一定的入门门槛,人才较少;

原生的一个很大特点就是独立,所以不太容易入门,而且 AndroidiOS都需要独立学习。

  • 分发成本高,更新缓慢,特别是发布应用商店后,需要等到审核周期;

原生应用更新是一个很大的问题, Android中还能直接下载整包APK进行更新,但是 iOS中,如果是发布 AppStore ,必须通过 AppStore地址更新,而每次更新都需要审核,所以无法达到及时更新。

1.4 Hybrid App

Hybrid App 指的是混合开发,也就是半原生半 Web 的开发模式,有跨平台效果,当然了,实质最终发布的仍然是独立的原生APP(各种的平台有各种的SDK)。

优点:

  • 学习和开发成本较低,可以跨平台,调试方便

Hybrid 开发模式下,由原生提供统一的 API 给 JS 调用,实际的主要逻辑由 HTML 和 JS 完成,最终放在 webview 中显示,这样只需要写一套代码即可,达到跨平台效果,另外也可以直接在浏览器中调试,很方便。

一般 Hybrid 中的跨平台最少可以跨三个平台: Android App ,iOS App ,普通 webkit 浏览器。

需要前端人员关注一些原生提供的API,具体的实现无需关心,没有新的学习内容。

  • 维护成本低,功能可复用,并且更容易更新;

虽然没有 web app 更新那么快速,但是 Hybrid 中也可以通过原生提供 api ,进行资源主动下载,达到只更新资源文件,不更新 apk(ipa) 的效果。

  • 功能更加完善,性能和体验要比起 web app 好太多;

因为可以调用原生api,所以很多功能只要原生提供出就可以实现,另外性能也比较接近原生。

  • 部分性能要求的页面可用原生实现;

这种模式是原生混合 web ,所以我们完全可以将交互强,性能要求高的页面用原生写,然后一些其它页面用 JS 写,嵌入 webview 中,达到最佳体验。

缺点:

  • 相比原生,性能仍然有较大损耗;

这种模式受限于 webview 的性能,相比原生而言有不少损耗,体验无法和原生相比。

  • 不适用于交互性较强的app;

这种模式的主要适用:一些新闻阅读类,信息展示类的 app ,不适用于一些交互较强或者性能要求较高的 app (比如动画较多就不适合)。

1.5 三者区别

三者使用场景对比:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_javascript_02

三者技术特征对比:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_javascript_03

另外增加 ReactNative 一起放入作对比。

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_android_04


1.6 三者如何选择

这里简单介绍几种情况,具体还是要以实际项目技术评估结果为主。

  • 选择纯 Native App 模式的情况:

性能要求极高,体验要求极好,不追求开发效率

  • 选择 Web App 模式的情况:

不追求用户体验和性能,对离线访问没要求,正常来说,如果追求性能和体验,都不会选用web app。

  • 选择 Hybrid App 模式的情况

大部分情况下的App都推荐采用这种模式,这种模式可以用原生来实现要求高的界面,对于一些比较通用型,展示型的页面完全可以用web来实现,达到跨平台效果,提升效率。一般好一点的Hybrid方案,都会把资源放在本地的,可以减少网络流量消耗

  • 选择React Native App模式的情况

追求性能,体验,同时追求开发效率,而且有一定的技术资本,舍得前期投入。

React Native这种模式学习成本较高,所以需要前期投入不少时间才能达到较好水平,但是有了一定水准后,开发起来它的优势就体现出来了,性能不逊色原生,而且开发速度也很快

二、什么是 Cordova,它的优缺点是什么

参考文章:[《浅谈Cordova框架》]

2.1 Cordova 简介

Cordova 是一个用基于 HTML、CSS 和 JavaScript 的,用于创建跨平台移动应用程序的快速开发平台。它使开发者能够利用iPhone、Android、Palm、Symbian、WP7、Bada和Blackberry等智能手机的核心功能——包括地理定位、加速器、联系人、声音和振动等,此外 Cordova 拥有丰富的插件,可以调用。

也可以用来开发原生和WebView组件之间的插件接口

2.2 Cordova 架构图

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_android_05

架构图介绍:

  • Web App

用于存放我们程序的代码,包括业务逻辑,还有一些运行需要的资源(如:CSS,JavaScript,图片,媒体文件等)。应用的实现是通过 web 页面,默认的本地文件名称是 ​index.html​ ,应用执行在原生应用包装的 WebView 中,这个原生应用是你分发到应用商店中的。

  • WebView

Cordova 用的 WebView 可以给应用提供完整用户访问界面,使得应用混合了 Webview 和原生的应用组件。

  • Cordova Plugins

插件是 Cordova 生态系统的重要组成部分。它提供了 Cordova 和原生组件相互通信的接口,并绑定到了标准的设备API上,这使你能够通过 JavaScript 调用原生代码

2.3 优缺点

优点:

  • 跨平台,开发简单,学习成本低;
  • 框架多,插件多,可自定义插件;
  • 发展最早,社区资源丰富;

缺点:

  • WebView性能低下时,用户体验差,反应慢;
  • 中文文档资源少;
  • 调试不方便,既不像原生那么好调试,也不像纯web那种调试;

三、Cordova 插件的原理是什么

Cordova 插件就是一些附加代码用来提供原生组件的 JavaScript 接口,它允许你的 App 可以使用原生设备的能力,超越了纯粹的 Web App。

Cordova 在 iOS 上的实现原理:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_06

3.1 工作流程

  1. Cordova 发起对原生的请求:
  2. cordova.exec(successCallback, failCallback, service, action, actionArgs);
  3. // successCallback: 成功回调方法
  4. // failCallback: 失败回调方法
  5. // server: 所要请求的服务名字
  6. // action: 所要请求的服务具体操作
  7. // actionArgs: 请求操作所带的参数

  8. 这五个参数并不是直接传给原生,Cordova JS 端会做以下处理:
  • 为每个请求生成一个唯一标识( ​​callbackId​​ ),并传给原生端,原生端处理完后,会把 ​​callbackId​​ 连同处理结果一起返回给 JS 端;
  • 以 ​​callbackId​​ 为 ​​key​​, ​​{success:successCallback,fail:failCallback}​​ 为 ​​value​​,把这个键值对保存在 JS 端的字典里, ​​successCallback​​ 与 ​​failCallback​​ 这两个参数不需要传给原生,原生返回结果时带上 ​​callbackId​​,JS 端就可以根据 ​​callbackId​​ 找到回调方法;
  • 每次 JS 请求,最后发到原生的数据包括: ​​callbackId​​, ​​service​​, ​​action​​, ​​actionArgs​​;

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_javascript_07


  1. 原生代码拿到 ​​callbackId​​、 ​​service​​、 ​​action​​ 及 ​​actionArgs​​ 后,会做以下处理:
  • 根据 ​​service​​ 参数找到对应插件类;
  • 根据 ​​action​​ 参数找到插件类中对应的处理方法,并把 ​​actionArgs​​ 作为处理方法请求参数的一部分传给处理方法;
  • 处理完成后,把处理结果及 ​​callbackId​​ 返回给 JS 端,JS 端收到后会根据 ​​callbackId​​ 找到回调方法,并把处理结果传给回调方法;

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_android_08

  1. JS 端根据 ​callbackId​​ 回调 ​​cordova.js​
  2. // 根据 callbackId 及是否成功标识,找到回调方法,并把处理结果传给回调方法
  3. callbackFromNative: function(callbackId, success, status, args, keepCallback) {
  4. var callback = cordova.callbacks[callbackId];
  5. if (callback) {
  6. if (success && status == cordova.callbackStatus.OK) {
  7. callback.success && callback.success.apply(null, args);
  8. } else if (!success) {
  9. callback.fail && callback.fail.apply(null, args);
  10. }

  11. // Clear callback if not expecting any more results
  12. if (!keepCallback) {
  13. delete cordova.callbacks[callbackId];
  14. }
  15. }
  16. }

四、什么是 JS Bridge,它的作用是什么


4.1 JS Bridge 介绍

JSBridge 简单来讲,主要是 给 JavaScript 提供调用 Native 功能的接口,让混合开发中的前端部分可以方便地使用地址位置、摄像头甚至支付等 Native 功能。

JSBridge 就像其名称中的 “Bridge” 的意义一样,是 Native 和非 Native 之间的桥梁,它的核心是 构建 Native 和非 Native 间消息通信的通道,而且是 双向通信的通道

JSBridge 另一个叫法及大家熟知的 Hybrid app 技术。

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_09

所谓 双向通信的通道:

  • JS 向 Native 发送消息 :

调用相关功能、通知 Native 当前 JS 的相关状态等。

  • Native 向 JS 发送消息 :

回溯调用结果、消息推送、通知 JS 当前 Native 的状态等。

4.2. JS Bridge 实现原理

参考文章:[《Hybrid APP基础篇(四)->JSBridge的原理》]

Android 和 iOS 的 JSBridge 实现方式:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_javascript_10

4.2.1 基本流程

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_android_11

  • H5 页面通过某种方式触发一个 ​url scheme​;
  • Native 捕获到 ​url scheme​,并进行分析和处理;
  • Native 调用 H5 的 JSBridge 对象传递回调;

原生的 WebView/UIWebView 控件已经能够和 JS 实现数据通信了,那为什么还要 JSBridge呢?

其实使用JSBridge有很多方面的考虑:

  • Android4.2以下, ​addJavascriptInterface​ 方式有安全漏掉。
  • iOS7以下,JS 无法调用 Native。
  • url scheme​ 交互方式是一套现有的成熟方案,可以完美兼容各种版本,对以前老版本技术的兼容。
4.2.1 实现流程(Android 为例)

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_12

  1. 拟定协议,参考 http 制定的协议为: ​jsbridge://className:port/methodName?jsonObj​;
  2. className // Android端实现暴露给前端的类名
  3. port // Android返回结果给前端的端口
  4. methodName // 前端需要调用的函数
  5. jsonObj // 前端给Android传递的参数
  6. 新建 HTML 文件命名为 ​index.html​​, 编写一个 ​​button​​ 绑定 ​​click​​ 事件;
  7. <button onclick="JSBridge.call(
  8. 'bridge',
  9. 'showToast',
  10. {'msg':'Hello JSBridge'},
  11. function(res){
  12. alert(JSON.stringify(res))
  13. }
  14. )">
  15. 测试showToast
  16. </button>
  17. 新建 JS 文件命名为 ​JSBridge.js​​, 第2步中的 ​​JSBridge.call​​ 即为调用 ​​JSBridge.js​​中的 ​​call​​ 方法,后面带了四个参数;
  18. call: function (obj, method, params, callback) {
  19. console.log(obj+" "+method+" "+params+" "+callback);
  20. var port = Util.getPort();
  21. console.log(port);
  22. this.callbacks[port] = callback;
  23. var uri=Util.getUri(obj,method,params,port);
  24. console.log(uri);
  25. window.prompt(uri, "");
  26. },

JSBridge.js​​ 中的 ​call​​ 方法,最后调用了 ​window.prompt​​ 方法,这个方法就是触发 Android 端 ​webChromeClient​的回调函数用的。

  1. window.prompt​​ 触发了 ​​WebChromeClient​​(这个需要使用函数 ​​WebView.setWebChromeClient​​(​​newWebChromeClietn()​​ )进行设定);

类中的如下回调 ​onJsPrompt​。这时就完成了前端与 Android端 的通信了,因为前端的信息都顺利通过这个函数传递给Android了。

  1. @Override
  2. public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
  3. result.confirm(JSBridge.callJava(view,message));
  4. return true;
  5. }
  6. Android 中会定义一个类 ​JSBridge.java​ 来管理暴露给前端使用的函数;

这个类有两个功能:

  • 暴露给前端的函数的动态注册功能。
  • 解析前端信息,调用了 Android 端对应的函数,这个示例中是: ​showToast​ 函数。

解析前端的信息,获取前端调用的函数名:

  1. Uri uri = Uri.parse(uriString);
  2. className = uri.getHost();
  3. param = uri.getQuery();
  4. port = uri.getPort() + "";
  5. String path = uri.getPath();
  6. HashMap< String, Method> methodHashMap = exposedMethod.get(className);
  7. Method method = methodHashMap.get(methodName);

通过获取的函数名,这里是 ​showToast​​,调用 Android 端的 ​showToast​函数。

  1. method.invoke(null,webView,new JSONObject(param),new Callback(webView,port));
  2. 定义类 ​BridgeImpl.java​​ 来具体的实现暴露给前端的所有函数。这里的 ​​showToast​​函数如下:
  3. public static void showToast(WebView webView, JSONObject param, final JSBridge.Callback callback){
  4. String message = param.optString("msg");
  5. Toast.makeText(webView.getContext(),message,Toast.LENGTH_LONG).show();
  6. if(null != callback){
  7. try {
  8. JSONObject object = new JSONObject();
  9. object.put("key","value");
  10. object.put("key1","vaule1");
  11. callback.apply(getJSONObject(0,"ok",object));
  12. }catch (Exception e){
  13. e.printStackTrace();
  14. }
  15. }
  16. }

五、请列举 Android 与 iOS 平台下 JS Bridge 的实现方式

这边代码比较多,我使用图片来展示,大家可以放大来查看。

5.1 Android 实现方式

5.1.1 Android 调用 JS 的 2 种方式
  1. 通过 ​WebView​  ​​loadUrl()​​:

JS 代码调用一定要在 ​onPageFinished()​ 回调之后才能调用,否则不会调用。

Web 端代码:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>前端代码</title>
  6. <script>
  7. // Android需要调用的方法
  8. function callJS(){
  9. alert("Android调用了JS的callJS方法");
  10. }
  11. </script>
  12. </head>
  13. </html>

Android 端代码:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_android_13

  1. 通过 ​WebView​  ​​evaluateJavascript()​​:
  2. // 只需要将第一种方法的loadUrl()换成下面该方法即可
  3. mWebView.evaluateJavascript(
  4. "javascript:callJS()",
  5. new ValueCallback<String>() {
  6. @Override
  7. public void onReceiveValue(String value) {
  8. //此处为 js 返回的结果
  9. }
  10. });
  11. }
5.1.2 JS 调用 Android 的 3 种方式
  1. 通过 ​​WebView​​ 的 ​​addJavascriptInterface()​​ 进行对象映射:

Android 映射:

  1. // 继承自Object类
  2. public class AndroidtoJs extends Object {
  3. // 定义JS需要调用的方法
  4. // 被JS调用的方法必须加入@JavascriptInterface注解
  5. @JavascriptInterface
  6. public void hello(String msg) {
  7. System.out.println("JS调用了Android的hello方法");
  8. }
  9. }

Web:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>前端代码</title>
  6. <script>
  7. function callAndroid(){
  8. // 由于对象映射,所以调用test对象等于调用Android映射的对象
  9. test.hello("js调用了android中的hello方法");
  10. }
  11. </script>
  12. </head>
  13. <body>
  14. //点击按钮则调用callAndroid函数
  15. <button type="button" id="button1" "callAndroid()"></button>
  16. </body>
  17. </html>

Android 端:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_14

  1. 通过 ​​WebViewClient​​ 的 ​​shouldOverrideUrlLoading()​​ 方法回调拦截 ​​url​​:

Web 端:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>前端代码</title>
  6. <script>
  7. function callAndroid(){
  8. /*约定的url协议为:js://webview?arg1=111&arg2=222*/
  9. document.location = "js://webview?arg1=111&arg2=222";
  10. }
  11. </script>
  12. </head>
  13. <!-- 点击按钮则调用callAndroid()方法 -->
  14. <body>
  15. <button type="button" id="button1"
  16. onclick="callAndroid()"
  17. >点击调用Android代码</button>
  18. </body>
  19. </html>

Android 端:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_javascript_15

  1. 通过 WebChromeClient 的方法回调拦截JS对话框方法:

通过 WebChromeClient 的 ​onJsAlert()​​ 、 ​onJsConfirm()​​ 、 ​onJsPrompt()​​方法回调拦截JS对话框 ​alert()​​ 、 ​confirm()​​、 ​prompt()​ 消息。

Web 端:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>前端代码</title>
  6. <script>
  7. function clickprompt(){
  8. // 调用prompt()
  9. var result=prompt("js://demo?arg1=111&arg2=222");
  10. alert("demo " + result);
  11. }
  12. </script>
  13. </head>
  14. <!-- 点击按钮则调用clickprompt() -->
  15. <body>
  16. <button type="button" id="button1"
  17. onclick="clickprompt()"
  18. >点击调用Android代码</button>
  19. </body>
  20. </html>

Android 端:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_javascript_16

5.2 iOS 实现方式

5.2.1 JS 调用 iOS 的 2 种方式
  1. 使用 ​​XMLHttpRequest​​ 发起请求的方式:

Web 端:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_17

XMLHttpRequest bridge:

JS 端使用 ​XMLHttpRequest​​ 发起了一个请求:​execXhr.open('HEAD',"/!gap_exec?"+(+newDate()),true);​​,请求的地址是 ​/!gap_exec​​;并把请求的数据放在了请求的 header 里面,见这句代码:​execXhr.setRequestHeader('cmds',iOSExec.nativeFetchMessages());​。

而在 Objective-C 端使用一个 ​NSURLProtocol​​ 的子类来检查每个请求,如果地址是 ​/!gap_exec​ 的话,则认为是 Cordova 通信的请求,直接拦截,拦截后就可以通过分析请求的数据,分发到不同的插件类(CDVPlugin 类的子类)的方法中:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_18

Cordova 中优先使用这种方式, ​Cordova.js​​ 中的注释有提及为什么优先使用 ​XMLHttpRequest​​ 的方式,及为什么保留第二种 ​iframe bridge​ 的通信方式:

  1. // XHR mode does not work on iOS 4.2, so default to IFRAME_NAV for such devices.
  2. // XHR mode’s main advantage is working around a bug in -webkit-scroll, which
  3. // doesn’t exist in 4.X devices anyways123

iframe bridge:

在 JS 端创建一个透明的 ​iframe​​,设置这个 ​ifame​​ 的 ​src​​ 为自定义的协议,而 ​ifame​​的 ​src​​更改时, ​UIWebView​​ 会先回调其 ​delegate​​ 的 ​webView:shouldStartLoadWithRequest:navigationType:​ 方法,关键代码如下:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_19

  1. 通过设置透明的 ​​iframe​​ 的 ​​src​​ 属性:
5.2.2 iOS 调用 JS 的方式

UIWebView​​ 有一个这样的方法 ​stringByEvaluatingJavaScriptFromString:​​,这个方法可以让一个 ​UIWebView​ 对象执行一段 JS 代码,这样就可以达到 Objective-C 跟 JS 通信的效果,在 Cordova 的代码中多处用到了这个方法,其中最重要的两处如下:

  1. 获取 JS 的请求数据:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_20

  1. 把 JS 请求的结果返回给 JS 端:

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_webview_21

结语

对于初入混合应用开发的小伙伴,这些会有点难度,但是好好理解下那几张流程图,再理一理思路,相信会有帮助😁

给大家加加油~~

关于我

本文首发在 [pingan8787个人博客] (http://www.pingan8787.com),如需转载请保留个人介绍

微信公众号

【Hybird】274-Hybird App 应用开发中 5 个必备知识点复习_android_22


举报

相关推荐

0 条评论