Hybrid App 应用 开发中 9 个必备知识点复习(WebView / 调试 等) 上

简介: Hybrid App 应用 开发中 9 个必备知识点复习(WebView / 调试 等) 上



前言

我们大前端团队内部 📖每周一练 的知识复习计划继续加油,本篇文章是 《Hybrid APP 混合应用专题》 主题的第二期和第三期的合集。

这一期共整理了 10 个问题,和相应的参考答案,文字和图片较多,建议大家可以收藏,根据文章目录来阅读

之前分享的每周内容,我都整理到掘金收藏集 📔《EFT每周一练》 上啦,欢迎点赞收藏咯💕💕。

内容回顾:

  1. 《EFT 每周分享 —— Hybrid App 应用开发中 5 个必备知识点复习》
  2. 《EFT 每周分享 —— HTTP 的15个常见知识点复习》
  3. 《EFT 每周分享 —— 数据结构与算法合集》

文章收录:

本系列所有文章,都将收录在 Github 上,欢迎点击查阅

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


一、iOS 平台中 UIWebView 与 WKWebView 有什么区别?

参考文章:《UIWebView与WKWebView》

UIWebView 是苹果继承于 UIView 封装的一个加载 web 内容的类,它可以加载任何远端的web数据展示在你的页面上,你可以像浏览器一样前进后退刷新等操作。不过苹果在 iOS8 以后推出了 WKWebView 来加载 Web,并应用于 iOS 和 OSX 中,它取代了 UIWebViewWebView ,在两个平台上支持同一套 API。

它脱离于 UIWebView 的设计,将原本的设计拆分成14个类,和3个代理协议,虽然是这样但是了解之后其实用法比较简单,依照职责单一的原则,每个协议做的事情根据功能分类。

WKWebViewUIWebView 的区别:

  • WKWebView 的内存远远没有 UIWebView 的开销大,而且没有缓存;
  • WKWebView 拥有高达 60FPS 滚动刷新率及内置手势;
  • WKWebView 支持了更多的 HTML5 特性;
  • WKWebView 高效的 app 和 web 信息交换通道;
  • WKWebView 允许 JavaScriptNitro 库加载并使用, UIWebView 中限制了;
  • WKWebView 目前缺少关于页码相关的 API;
  • WKWebView 提供加载网页进度的属性;
  • WKWebView 使用 Safari 相同的 JavaScript 引擎;
  • WKWebView 增加加载进度属性: estimatedProgress
  • WKWebView 不支持页面缓存,需要自己注入 cookie , 而 UIWebView 是自动注入 cookie
  • WKWebView 无法发送 POST 参数问题;
  • WKWebView 可以和js直接互调函数,不像 UIWebView 需要第三方库 WebViewJavascriptBridge 来协助处理和 js 的交互;

注意:

大多数App需要支持 iOS7 以上的版本,而 WKWebView 只在 iOS8 后才能用,所以需要一个兼容性方案,既 iOS7 下用 UIWebViewiOS8 后用 WKWebView 。但是目前 IOS10 以下的系统以及很少了,

小结:

WKWebView 相较于 UIWebView 在整体上有较大的提升,满足 iOS 上面使用同一套控件的功能,同时对整个内存的开销以及滚动刷新率和 JS 交互做了优化的处理。

依据职责单一原则,拆分成了三个协议去实现 WebView 的响应,解耦了 JS 交互和加载进度的响应处理。

WKWebView 没有做缓存处理,所以对网页需要缓存的加载性能要求没那么高的还是可以考虑 UIWebView


二、WKWebView 有哪一些坑?

参考文章:《WKWebView 那些坑》

1. WKWebView 白屏问题

WKWebView 实际上是个多进程组件,这也是它加载速度更快,内存暂用更低的原因。

UIWebView 上当内存占用太大的时候,App Process 会 crash;而在 WKWebView 上当总体的内存占用比较大的时候,WebContent Process 会 crash,从而出现白屏现象。

解决办法:

  1. 借助 WKNavigtionDelegate

WKWebView 总体内存占用过大,页面即将白屏的时候,系统会调用上面的回调函数,我们在该函数里执行[webView reload](这个时候 webView.URL 取值尚不为 nil)解决白屏问题。在一些高内存消耗的页面可能会频繁刷新当前页面,H5侧也要做相应的适配操作。

  1. 检测 webView.title 是否为空

并不是所有 H5 页面白屏的时候都会调用上面的回调函数,比如,最近遇到在一个高内存消耗的 H5 页面上 present 系统相机,拍照完毕后返回原来页面的时候出现白屏现象(拍照过程消耗了大量内存,导致内存紧张,WebContent Process 被系统挂起),但上面的回调函数并没有被调用。在 WKWebView 白屏的时候,另一种现象是 webView.titile 会被置空, 因此,可以在 viewWillAppear 的时候检测 webView.title 是否为空来 reload 页面。

2. WKWebView Cookie 问题

WKWebViewCookie 问题在于 WKWebView 发起的请求不会自动带上存储于 NSHTTPCookieStorage 容器中的 Cookie,而在 UIWebView 会自动带上 Cookie

原因是:

WKWebView 拥有自己的私有存储,不会将 Cookie 存入到标准的 Cookie 容器NSHTTPCookieStorage 中。

实践发现 WKWebView 实例其实也会将 Cookie 存储于 NSHTTPCookieStorage 中,但存储时机有延迟,在 iOS 8 上,当页面跳转的时候,当前页面的 Cookie 会写入 NSHTTPCookieStorage 中,而在 iOS 10 上,JS 执行 document.cookie 或服务器 set-cookie 注入的 Cookie 会很快同步到 NSHTTPCookieStorage 中,FireFox 工程师曾建议通过 reset WKProcessPool 来触发 Cookie 同步到 NSHTTPCookieStorage 中,实践发现不起作用,并可能会引发当前页面 session cookie 丢失等问题。

解决办法1:

WKWebView loadRequest 前,在 request header 中设置 Cookie, 解决首个请求 Cookie 带不上的问题;

解决办法2:

通过 document.cookie 设置 Cookie 解决后续页面(同域)Ajax``、iframe 请求的 Cookie 问题;(注意:document.cookie() 无法跨域设置 cookie)。

3. WKWebView loadRequest 问题

WKWebView 上通过 loadRequest 发起的 post 请求 body 数据会丢失,同样是由于进程间通信性能问题HTTPBody 字段被丢弃。

4. WKWebView NSURLProtocol问题

WKWebView 在独立于 app 进程之外的进程中执行网络请求,请求数据不经过主进程,因此,在 WKWebView 上直接使用 NSURLProtocol 无法拦截请求。

解决办法:

由于 WKWebView 在独立进程里执行网络请求。一旦注册 http(s) scheme 后,网络请求将从 Network Process 发送到 App Process,这样 NSURLProtocol 才能拦截网络请求。在 webkit2 的设计里使用 MessageQueue 进行进程之间的通信,Network Process 会将请求 encode 成一个 Message,然后通过 IPC 发送给 App Process。出于性能的原因,encode 的时候 HTTPBodyHTTPBodyStream 这两个字段会被丢弃掉了。

5. WKWebView 页面样式问题

WKWebView 适配过程中,我们发现部分 H5 页面元素位置向下偏移或被拉伸变形,追踪后发现主要是 H5 页面高度值异常导致。

解决办法:

调整 WKWebView 布局方式,避免调整 webView.scrollView.contentInset 。实际上,即便在 UIWebView 上也不建议直接调整 webView.scrollView.contentInset 的值,这确实会带来一些奇怪的问题。如果某些特殊情况下非得调整 contentInset 不可的话,可以通过下面方式让H5页面恢复正常显示。

6. WKWebView 截屏问题

WKWebView 下通过 -[CALayer renderInContext:]实现截屏的方式失效,需要通过以下方式实现截屏功能:

@implementation UIView (ImageSnapshot) 
- (UIImage*)imageSnapshot { 
    UIGraphicsBeginImageContextWithOptions(self.bounds.size,YES,self.contentScaleFactor);
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES]; 
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return newImage; 
} 
@end

然而这种方式依然解决不了 webGL 页面的截屏问题,截屏结果不是空白就是纯黑图片。

解决办法:

无奈之下,我们只能约定一个JS接口,让游戏开发商实现该接口,具体是通过 canvasgetImageData()方法取得图片数据后返回 base64 格式的数据,客户端在需要截图的时候,调用这个JS接口获取base64 String并转换成 UIImage

7. WKWebView crash问题

如果 WKWebView 退出的时候,JS刚好执行了 window.alert(), alert 框可能弹不出来,completionHandler 最后没有被执行,导致 crash

另一种情况是在 WKWebView 一打开,JS就执行 window.alert(),这个时候由于 WKWebView 所在的 UIViewController 出现( pushpresent )的动画尚未结束,alert 框可能弹不出来,completionHandler 最后没有被执行,导致 crash

8. 视频自动播放

WKWebView 需要通过 WKWebViewConfiguration.mediaPlaybackRequiresUserAction 设置是否允许自动播放,但一定要在 WKWebView 初始化之前设置,在 WKWebView 初始化之后设置无效。

9. goBack API问题

WKWebView 上调用 -[WKWebView goBack], 回退到上一个页面后不会触发window.onload() 函数、不会执行JS。

10. 页面滚动速率

WKWebView 需要通过 scrollView delegate 调整滚动速率:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    scrollView.decelerationRate = UIScrollViewDecelerationRateNormal; 
}

三、Crosswalk 是什么,它有什么作用?

参考网站: 《Crosswalk Github》 参考文章: 《Crosswalk入门》

Crosswalk 是一款开源的 web 引擎。目前 Crosswalk 正式支持的移动操作系统包括 Android 和 Tizen ,在 Android 4.0 及以上的系统中使用 Crosswalk 的 Web 应用程序在 HTML5 方面可以有一致的体验,同时和系统的整合交互方面(比如启动画面、权限管理、应用切换、社交分享等等)可以做到类似原生应用

现在 Crosswalk 已经成为众多知名 HTML5 平台和应用的推荐引擎,包括 Google Mobile Chrome App 、 Intel XDK 、 Famo.us 和 Construct2 等等,未来的 Cordova 4.0 也计划集成 Crosswalk

四、常见的 WebView 性能优化方案有哪一些?

0. 问题分析

首先需要了解,对于一个普通用户来讲,打开一个 WebView 通常会经历哪几个阶段,一般有这些:

  1. 交互无反馈;
  2. 到达新的页面,页面白屏;
  3. 页面基本框架出现,但是没有数据;页面处于loading状态;
  4. 出现所需的数据;

当 App 首次打开时,默认是并不初始化浏览器内核的;只有当创建 WebView 实例的时候,才会创建 WebView 的基础框架。

所以与浏览器不同,App 中打开 WebView 的第一步并不是建立连接,而是启动浏览器内核。

于是我们找到了“为什么WebView总是很慢”的原因之一:

  • 在浏览器中,我们输入地址时(甚至在之前),浏览器就可以开始加载页面。
  • 而在客户端中,客户端需要先花费时间初始化 WebView 完成后,才开始加载。

而这段时间,由于WebView还不存在,所有后续的过程是完全阻塞的。因此由于这段过程发生在 native 的代码中,单纯靠前端代码是无法优化的;大部分的方案都是前端和客户端协作完成,以下是几个业界采用过的方案:

1. 全局 WebView

在客户端刚启动时,就初始化一个全局的 WebView 待用,并隐藏,当用户访问了 WebView 时,直接使用这个 WebView 加载对应网页,并展示。

这种方法可以比较有效的减少 WebView 在App中的首次打开时间。当用户访问页面时,不需要初始化 WebView 的时间。

当然这也带来了一些问题,包括:

  • 额外的内存消耗。
  • 页面间跳转需要清空上一个页面的痕迹,更容易内存泄露。

2. WebView 动态加载

参考文章:《WebView常用优化方案》

WebView 动态加载。就是不在 xml 中写 WebView ,写一个 layout ,然后把 WebView add 进去。

WebView mWebView = new WebView(getApplicationgContext());
LinearLayout mll = findViewById(R.id.xxx);
mll.addView(mWebView);
protected void onDestroy() {
    super.onDestroy();
    mWebView.removeAllViews();
    mWebView.destroy()
}

这里用的 getApplicationContext() 也是防止内存溢出,这种方法有一个问题。如果你需要在 WebView 中打开链接或者你打开的页面带有 flash,获得你的 WebView 想弹出一个 dialog ,都会导致从 ApplicationContextActivityContext 的强制类型转换错误,从而导致你应用崩溃。

这是因为在加载 flash 的时候,系统会首先把你的 WebView 作为父控件,然后在该控件上绘制 flash ,他想找一个 ActivityContext 来绘制他,但是你传入的是 ApplicationContext 。然后就崩溃了。

3. 独立的web进程,与主进程隔开

参考文章:《WebView常用优化方案》

这个方法被运用于类似 qq ,微信这样的超级 app 中,这也是解决任何 WebView 内存问题屡试不爽的方法 对于封装的 webactivity ,在 manifest.xml 中设置。

<activity 
    android:name=".webview.WebViewActivity" 
    android:launchMode="singleTop" 
    android:process=":remote" 
    android:screenOrientation="unspecified" 
/>

然后在关闭 webactivity 时销毁进程:

@Overrideprotected void onDestroy() {                
super.onDestroy(); 
    System.exit(0);
}

关闭浏览器后便销毁整个进程,这样一般 95% 的情况下不会造成内存泄漏之类的问题,但这就涉及到 android 进程间通讯,比较不方便处理,优劣参半,也是可选的一个方案。

4. WebView 释放

参考文章:《WebView常用优化方案》

public void destroy() {
    if (mWebView != null) {
        // 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再
        // destory()
        ViewParent parent = mWebView.getParent();
        if (parent != null) {
            ((ViewGroup) parent).removeView(mWebView);
        }
        mWebView.stopLoading();
        // 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
        mWebView.getSettings().setJavaScriptEnabled(false);
        mWebView.clearHistory();
        mWebView.clearView();
        mWebView.removeAllViews();
        try {
            mWebView.destroy();
        } catch (Throwable ex) {
        }
    }
}


目录
相关文章
|
2月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
754 7
|
2月前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
775 1
|
8天前
|
JSON 缓存 前端开发
HarmonyOS NEXT 5.0鸿蒙开发一套影院APP(附带源码)
本项目基于HarmonyOS NEXT 5.0开发了一款影院应用程序,主要实现了电影和影院信息的展示功能。应用包括首页、电影列表、影院列表等模块。首页包含轮播图与正在热映及即将上映的电影切换显示;电影列表模块通过API获取电影数据并以网格形式展示,用户可以查看电影详情;影院列表则允许用户选择城市后查看对应影院信息,并支持城市选择弹窗。此外,项目中还集成了Axios用于网络请求,并进行了二次封装以简化接口调用流程,同时添加了请求和响应拦截器来处理通用逻辑。整体代码结构清晰,使用了组件化开发方式,便于维护和扩展。 该简介概括了提供的内容,但请注意实际开发中还需考虑UI优化、性能提升等方面的工作。
54 11
|
5天前
|
前端开发 数据库 UED
uniapp开发,前后端分离的陪玩系统优势,陪玩app功能特点,线上聊天线下陪玩,只要4800
前后端分离的陪玩系统将前端(用户界面)和后端(服务器逻辑)分开开发,前者负责页面渲染与用户交互,后者处理数据并提供接口。该架构提高开发效率、优化用户体验、增强可扩展性和稳定性,降低维护成本,提升安全性。玩家可发布陪玩需求,陪玩人员发布服务信息,支持在线聊天、预约及线下陪玩功能,满足多样化需求。[演示链接](https://www.51duoke.cn/games/?id=7)
|
11天前
|
供应链 搜索推荐 API
1688APP原数据API接口的开发、应用与收益(一篇文章全明白)
1688作为全球知名的B2B电商平台,通过开放的原数据API接口,为开发者提供了丰富的数据资源,涵盖商品信息、交易数据、店铺信息、物流信息和用户信息等。本文将深入探讨1688 APP原数据API接口的开发、应用及其带来的商业收益,包括提升流量、优化库存管理、增强用户体验等方面。
66 6
|
12天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
44 3
|
18天前
|
移动开发 小程序 PHP
校园圈子论坛系统采取的PHP语音和uni账号开发的小程序APP公众号H5是否只需要4800元?是的,就是只需要4800元
关于校园圈子论坛系统采用PHP语言和uni-app开发的小程序、APP、公众号和H5是否仅需4800元这个问题,实际上很难给出一个确定的答案。这个价格可能受到多种因素的影响
49 8
|
14天前
|
人工智能 小程序 数据处理
uni-app开发AI康复锻炼小程序,帮助肢体受伤患者康复!
近期,多家康复机构咨询AI运动识别插件是否适用于肢力运动受限患者的康复锻炼。本文介绍该插件在康复锻炼中的应用场景,包括康复运动指导、运动记录、恢复程度记录及过程监测。插件集成了人体检测、姿态识别等功能,支持微信小程序平台,使用便捷,安全可靠,帮助康复治疗更加高效精准。
|
4天前
|
安全 算法 机器人
双重防护!红娘相亲app搭建开发,婚恋交友系统登录方式,密码+验证码的优势
在婚恋交友系统中,密码和验证码是两种重要的安全措施。密码用于验证用户身份,应设置为复杂组合以防止未经授权的访问;验证码则通过图形或字符识别,防止自动化攻击如暴力破解和注册机器人。两者同时开启可显著提高安全性,防止暴力破解和自动化注册,提升用户信任感。建议要求强密码、定期更新验证码样式,并在可疑登录时增加验证码复杂性。这样既能保障用户信息安全,又兼顾了用户体验。 ![交友11111.jpg](https://ucc.alicdn.com/pic/developer-ecology/hy2p6wcvgk4oe_c9eb8d6eb8144866b0cd1d96ffb0c907.jpg)
|
1月前
|
人工智能 小程序 搜索推荐
uni app下开发AI运动小程序解决方案
本文介绍了在小程序中实现AI运动识别的解决方案。该方案依托于UNI平台,通过高效便捷的插件形式,实现包括相机抽帧控制、人体识别、姿态识别等在内的多项功能,无需依赖后台服务器,大幅提高识别效率和用户体验。方案内置多种运动模式,支持自定义扩展,适用于AI健身、云上赛事、AI体测等多场景,适合新开发和存量改造项目。