深入理解Android WebView的加载流程与事件回调
文章目录
- 一、WebView 加载流程时序图
- 二、WebView 加载流程回调函数说明
- 三、`AwContents`
- 3.1 主要功能和职责
- 3.2 架构和实现
- 3.3 使用场景
- 四、利用WebView回调函数检测白屏
- 4.1 使用`onPageStarted`和`onPageFinished`检测加载时间
- 4.2 利用`onReceivedError`和`onReceivedHttpError`检测加载错误
- 4.3 使用`shouldInterceptRequest`监控资源加载
- 4.4 使用`onPageCommitVisible`
- 4.5 结合JavaScript和`evaluateJavascript`
- 五、结论
在Android开发中,WebView用于显示网页和执行JavaScript。理解其加载流程和事件回调对于开发一个功能丰富且用户友好的基于Web的应用至关重要。本文将详细介绍 WebView 加载一个URL时的整个流程和相关的事件回调,帮助开发者更好地掌握其使用方法和处理可能出现的问题。
一、WebView 加载流程时序图
当用户通过 WebView 加载一个URL时,整个过程涉及多个组件和一系列复杂的交互。下面是一个 WebView 加载URL的时序图,以及对每个回调事件的详细说明。
上面的时序图提供了一个清晰的视图,展示了从开始加载URL到页面加载完成的整个过程中WebView和WebViewClient的交互。每个回调都在特定的时机被触发,以处理不同的事件和状态变化。
二、WebView 加载流程回调函数说明

-
触发加载
用户或应用触发loadUrl()方法,开始加载指定的URL。 -
原生层处理
WebView调用其底层实现(通常是AwContents的nativeLoadUrl()方法)来开始网络请求。 -
页面加载的各阶段
- 页面加载开始:此时,
WebViewClient的onPageStarted()方法被调用,标志着页面加载的开始。 - 资源请求拦截:
shouldInterceptRequest()方法可能会被多次调用,允许开发者拦截、修改或替换正在加载的资源。 - 资源加载:对于页面上的每个资源(如图片、CSS文件等),
onLoadResource()方法会被调用。
- 处理特殊事件
在加载过程中,WebView可能会遇到各种需要特殊处理的情况:
- 表单重提交:
onFormResubmission()被调用,询问用户是否重新提交表单。 - HTTP认证请求:
onReceivedHttpAuthRequest()请求HTTP认证信息。 - 客户端证书请求:
onReceivedClientCertRequest()提供客户端证书。 - SSL错误处理:
onReceivedSslError()处理SSL验证失败的情况。 - HTTP错误处理:
onReceivedHttpError()处理HTTP错误响应。 - 重定向过多:
onTooManyRedirects()处理页面重定向问题。 - 安全浏览命中:
onSafeBrowsingHit()处理访问到被标记为不安全的网页。
- 页面内容显示
- 页面即将可见:
onPageCommitVisible()方法被调用,标志着页面内容即将显示在屏幕上。 - 页面加载完成:最终,
onPageFinished()方法被调用,通知应用页面已完全加载。
每个回调方法都有其特定的用途,例如,shouldOverrideUrlLoading() 允许开发者决定是否拦截URL加载,而 onScaleChanged() 则用于处理缩放事件。正确处理这些回调可以极大地增强应用的功能性和用户体验。
三、AwContents
本节介绍时序图中的AwContents。AwContents 是 Android WebView 的一个核心组件,它在 Android WebView 架构中扮演着非常重要的角色。AwContents 是 Chromium 项目的一部分,它负责管理 WebView 的内容渲染和事件处理。在 Android 系统中,AwContents 作为 WebView 的底层实现,提供了与 Chromium 引擎的直接交互接口。
3.1 主要功能和职责
-
内容渲染:
AwContents负责将网页内容渲染到 WebView 组件上。它使用 Chromium 的渲染引擎(Blink)来解析 HTML、CSS 和 JavaScript,确保网页内容能够正确显示。 -
事件处理:
它处理来自上层 WebView 和 WebViewClient 的各种事件和请求,如页面加载、资源请求、导航事件等,并将这些事件转发到 Chromium 引擎。 -
JavaScript 交互:
AwContents提供了与 JavaScript 代码交互的接口,允许 Android 应用与网页中的 JavaScript 代码进行通信。 -
安全和隐私:
它实现了多种安全措施,如同源策略、内容安全策略等,以保护用户的安全和隐私。 -
网络请求管理:
AwContents管理所有网络请求,包括图片、CSS 文件、JavaScript 文件等资源的加载。它支持自定义网络请求的处理,例如通过shouldInterceptRequest()方法拦截和修改请求。
3.2 架构和实现
AwContents 是一个桥接类,它连接了 Android 的 WebView API 和 Chromium 的底层实现。在 Android WebView 的架构中,AwContents 位于 Java 层和 native 层之间,它通过 JNI(Java Native Interface)与 native 代码进行交互。
在 native 层,AwContents 对应的实现是 content::WebContents,这是 Chromium 中用于管理网页内容的核心类。WebContents 负责页面的生命周期管理、渲染进程管理和页面内容的实际渲染。
3.3 使用场景
开发者通常不直接与 AwContents 交互,而是通过 WebView 提供的高级 API 来进行开发。然而,了解 AwContents 的工作原理对于解决 WebView 中的高级问题、性能优化以及实现自定义功能非常有帮助。
AwContents 是 Android WebView 中的一个关键组件,它使得 WebView 能够利用 Chromium 引擎的强大功能,提供高性能和高兼容性的网页浏览体验。
四、利用WebView回调函数检测白屏
在Android开发中,使用WebView时偶尔会遇到白屏问题,这通常是由于网页加载不完全、资源加载失败或者JavaScript错误等原因引起的。利用WebView的回调函数可以帮助我们检测并诊断这种白屏问题。以下是一些策略和步骤,展示如何使用WebView的回调函数来检测白屏:
4.1 使用onPageStarted和onPageFinished检测加载时间
白屏可能是因为页面加载时间过长。通过记录onPageStarted和onPageFinished之间的时间差,可以判断页面是否在合理的时间内完成加载。
webView.setWebViewClient(new WebViewClient() {long startTime;@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);startTime = System.currentTimeMillis();}@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);long loadTime = System.currentTimeMillis() - startTime;if (loadTime > ACCEPTABLE_LOAD_TIME) {// 记录或处理加载时间过长的情况}}
});
4.2 利用onReceivedError和onReceivedHttpError检测加载错误
这些回调函数可以帮助我们捕获在加载过程中发生的错误,这些错误可能会导致页面内容无法正确显示,从而出现白屏。
webView.setWebViewClient(new WebViewClient() {@Overridepublic void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {super.onReceivedError(view, request, error);// 处理加载错误}@Overridepublic void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {super.onReceivedHttpError(view, request, errorResponse);// 处理HTTP错误}
});
4.3 使用shouldInterceptRequest监控资源加载
如果关键资源(如CSS或JavaScript文件)加载失败,可能会导致页面显示不完整或白屏。通过shouldInterceptRequest可以监控这些资源的加载情况。
webView.setWebViewClient(new WebViewClient() {@Overridepublic WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {// 检查请求的资源,记录加载失败的资源return super.shouldInterceptRequest(view, request);}
});
4.4 使用onPageCommitVisible
onPageCommitVisible在页面内容即将显示时调用,如果在这个阶段页面内容为空或不完整,可能是一个白屏的迹象。但是,onPageCommitVisible回调本身并不能直接提供页面内容的信息,我们需要结合其他方法来实现这个目标。一种可能的方法是在onPageCommitVisible回调中使用evaluateJavascript来检查页面的DOM结构。例如,我们可以检查某个关键元素是否存在,或者是否有内容。以下是一个示例:
webView.setWebViewClient(new WebViewClient() {@Overridepublic void onPageCommitVisible(WebView view, String url) {super.onPageCommitVisible(view, url);// 检查页面内容是否可见或部分内容是否缺失view.evaluateJavascript("(function() { return document.getElementById('keyElement').innerHTML; })();", new ValueCallback<String>() {@Overridepublic void onReceiveValue(String value) {if (value == null || value.isEmpty()) {// 如果关键元素不存在或没有内容,那么可能存在白屏问题Log.e("WebView", "Key element is missing or empty");}}});}
});
在这个示例中,我们假设keyElement是页面中的一个关键元素,我们通过JavaScript代码获取这个元素的内容,然后在回调中检查这个内容是否存在。如果不存在,那么可能存在白屏问题。
实际的检查方法可能需要根据你的具体需求进行调整。例如,你可能需要检查多个元素,或者使用更复杂的JavaScript代码来检查页面的状态。
4.5 结合JavaScript和evaluateJavascript
通过注入JavaScript代码检查DOM元素的存在或内容,可以帮助确认页面是否正确渲染。
webView.evaluateJavascript("(function() { return document.body.innerHTML; })();", new ValueCallback<String>() {@Overridepublic void onReceiveValue(String html) {if (html.isEmpty()) {// 处理白屏情况}}
});
通过上述方法,结合日志记录和异常处理机制,可以有效地检测和诊断WebView中的白屏问题。这些技术不仅可以帮助开发者提高应用的稳定性和用户体验,还可以在开发和测试阶段快速定位问题。
五、结论
WebView 的加载流程涉及复杂的交互和多个阶段,每个阶段都可能触发不同的事件回调。作为开发者,理解这些过程和回调的时机及其作用是非常重要的。这不仅可以帮助我们更有效地使用 WebView,还可以在开发过程中预见并解决潜在问题,从而创建更加稳定和可靠的应用。
相关文章:
深入理解Android WebView的加载流程与事件回调
文章目录 一、WebView 加载流程时序图二、WebView 加载流程回调函数说明三、AwContents3.1 主要功能和职责3.2 架构和实现3.3 使用场景 四、利用WebView回调函数检测白屏4.1 使用onPageStarted和onPageFinished检测加载时间4.2 利用onReceivedError和onReceivedHttpError检测加…...
机器视觉相机自动对焦算法
第一,Brenner梯度法、 第二,Tenegrad梯度法、 第三,laplace梯度法、 第四,方差法、 第五,能量梯度法。 此实例通过使用Halcon实现5种清晰度算法函数: 1. 方差算法函数; 2. 拉普拉斯能量函数…...
StarTowerChain:开启去中心化创新篇章
官网: www.startower.fr 在当今创新驱动的时代,StarTowerChain 以其独特的去中心化创新模式,为我们带来了新的希望和机遇。去中心化,这个充满活力与创造力的理念,正引领着我们走向未来的创新之路。 StarTowerChain …...
SpringCloudStream使用StreamBridge实现延时队列
利用RabbitMQ实现消息的延迟队列 一、安装RabbitMQ 1、安装rabbitmq 安装可以看https://blog.csdn.net/qq_38618691/article/details/118223851,进行安装。 2、安装插件 安装完毕后,exchange是不支持延迟类型的,需要手动安装插件,需要和安装的rabbitmq版本一致 https:…...
MATLAB中head函数用法
目录 语法 说明 示例 显示矩阵的前八行 显示表的前三行 返回表的前八行 head函数的功能是获取数组或表的顶行。 语法 head(A) head(A,k) B head(___) 说明 head(A) 在命令行窗口中显示数组、表或时间表 A 的前八行,但不存储值。 head(A,k) 显示 A 的前 k …...
golang 基本数据类型
1. go语言的数据类型简介 golang的数据类型分为两大类,一类是基本数据类型和符合数据类型; 按照传递的内容分:传递本身数据和传递地址; golang和java很相似,都是值传递,不过分为传递的值和传递的地址&a…...
各种查询sql介绍
1. 关联查询(JOIN) 关联查询用于从多个表中检索数据。它基于两个或多个表之间的共同字段(通常是主键和外键)来组合数据。 内连接(INNER JOIN): sql SELECT a.name, b.order_date FROM custome…...
Guava防击穿回源-异步防击穿
异步防击穿策略 在高并发环境下,缓存击穿(Cache Stampede)是一种常见的问题。当缓存中的热点数据失效或未命中时,大量并发请求同时访问后端数据源(如数据库),可能导致后端系统压力骤增,甚至出现崩溃。为了有效防止这种情况,可以利用Guava提供的异步缓存加载机制(类似…...
人工智能正在扼杀云计算的可持续性
可持续性曾是公共云计算中备受推崇的优势。企业和云提供商大肆宣扬他们的绿色计划,推广采用可再生能源的数据中心,以减少碳足迹。 近几个月来,这个话题已悄然淡出人们的视线。罪魁祸首是什么?对人工智能功能的无限需求正在推动云…...
C# 条形码、二维码标签打印程序
1、条码标答打印主界面 2、打印设置 3、生成QR代码 private void GetBarcode_T(string lr) { QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();//创建一个对象 qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE; //设置编码测量…...
嵌入式入门学习——6Protues点亮数码管,认识位码和段码,分辨共阴还是共阳(数字时钟第一步)
0 系列文章入口 嵌入式入门学习——0快速入门,Let‘s Do It! 首先新建基于Arduino UNO的protues工程,见本系列第3篇文章 1 点“P”按钮找器件 2 输入“seg”或“digit”查找数码管器件 3 找到我们想要的6位7段数码管 4如图A、B…DP都是段码…...
poisson过程——随机模拟(Python和R实现)
Python实现 exponential()使用,自动poisson过程实现。 import numpy as np import matplotlib.pyplot as plt# Parameters lambda_rate 5 # rate parameter (events per time unit) T 10 # total time# Generate Poisson process times np.random.exponential(…...
100 种下划线 / 覆盖层动画 | 终极 CSS(层叠样式表)集合
还在为你的菜单项和链接寻找动画效果而感到疲惫吗? 不用再找了!这里列出了 100 多种不同的动画。从简单的到更复杂的,你肯定能找到自己想要的。 无需 SVG(可缩放矢量图形),无需 JavaScript(脚…...
华为ICT大赛2024-2025网络赛道考试分析
华为ICT大赛2024-2025正在报名中,网络赛道的同学如何备考,了解考试内容呢? 一、考试概况 华为ICT大赛分为4个赛段,分别为省赛初赛、省赛复赛、中国总决赛,全球总决赛。其中对应的能力级别分别如下: 省赛…...
linux 效率化 - 输入法 - fcitx5
安装 Fcitx5 1. 卸载 ibus 框架 由于 ibus 和 fcitx 可能会冲突,先卸载 ibus(暂未确认原因) sudo apt remove --purge ibus2. 安装 fcitx5 输入法框架 sudo apt update sudo apt install fcitx5 fcitx5-chinese-addons fcitx5-frontend-gtk…...
YOLOv11改进策略【卷积层】| 替换骨干网络 CVPR-2024 RepViT 轻量级的Vision Transformers架构
一、本文介绍 本文记录的是基于RepVit的YOLOv11轻量化改进方法研究。RepVit的网络结构借鉴ViT的设计理念,通过分离的token mixe和channel mixer减少推理时的计算和内存成本,同时减少扩展比率并增加宽度,降低延迟,并通过加倍通道来弥补参数大幅减少的问题,提高了准确性。本…...
一天认识一个硬件之路由器
今天来给大家分享一下路由器的知识,先来说一下什么是路由器,路由器是一种计算机网络设备,它的主要作用是在不同的网络之间转发数据包,实现数据的传输和共享,介绍完了什么是路由器,再来介绍一下路由器的定义…...
【scene_manager】与 MoveIt 机器人的规划场景进行交互
scene_manager Scene Manager包是由 Robotnik 创建的 ROS 包,旨在帮助构建和与 MoveIt 机器人的规划场景进行交互。 背景信息 MoveIt 规划场景 是一个用于存储机器人周围世界的表示(外部碰撞)以及机器人自身状态(内部碰撞和当…...
数据结构单向链表的插入和删除(一)
链表 一、链表结构: (物理存储结构上不连续,逻辑上连续;大小不固定)二、单链表:三、单项链表的代码实现:四、开发可用的链表:四、单链表的效率分析: 一、链表结构&#x…...
鸿蒙网络编程系列30-断点续传下载文件示例
1. 断点续传简介 在文件的下载中,特别是大文件的下载中,可能会出现各种原因导致的下载暂停情况,如果不做特殊处理,下次还需要从头开始下载,既浪费了时间,又浪费了流量。不过,HTTP协议通过Range…...
用Docker三分钟部署MetaGPT开发环境(附LLM本地化方案)
三分钟容器化部署MetaGPT全栈开发环境实战指南 容器化部署的价值与优势 在当今快速迭代的AI开发领域,环境配置一直是困扰开发者的首要难题。传统部署方式需要处理Python版本管理、依赖冲突、CUDA驱动兼容等复杂问题,而容器化技术为这一痛点提供了优雅的解…...
02 前端 Web 开发 HTML5 + CSS3 + 移动 web 视频教程,前端web入门首选黑马程序员
02 前端 Web 开发 HTML5 CSS3 移动 web 视频教程,前端web入门首选黑马程序员 一、参考资料 【前端Web开发HTML5CSS3移动web视频教程,前端web入门首选黑马程序员】 https://www.bilibili.com/video/BV1kM4y127Li/?p17&share_sourcecopy_web&vd…...
Flutter鸿蒙应用集成图片加载与缓存功能
🔥Flutter鸿蒙应用集成图片加载与缓存功能(macOSDevEco Studio) 欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net📄 文章摘要 本文为Flutter for OpenHarmony 跨平台应用开发系列实战文章&…...
SEO 排名优化软件如何进行竞争对手分析
SEO 排名优化软件如何进行竞争对手分析 在当今的数字营销环境中,SEO(搜索引擎优化)已经成为企业提升在线可见度和吸引潜在客户的关键手段。而SEO排名优化软件作为这一领域的重要工具,其核心功能之一便是竞争对手分析。通过深入了…...
Linux基础之目录结构
初学Linux,首先需要弄清Linux 标准目录结构 / root — 启动Linux时使用的一些核心文件。如操作系统内核、引导程序Grub等。home — 存储普通用户的个人文件 ftp — 用户所有服务httpdsambauser1user2 bin — 系统启动时需要的执行文件(二进制…...
别再傻傻分不清!ESP32-S3上USB CDC、UART0和板载CH340到底谁在干活?
ESP32-S3串口全解析:快速识别USB CDC、UART0与CH340的实战指南 刚拿到ESP32-S3开发板时,很多开发者都会遇到一个令人困惑的场景——连接电脑后,设备管理器里突然冒出三四个COM端口,而Arduino IDE的下拉菜单里也列出一堆选项。到底…...
Go Context 控制流与生命周期管理
Go Context 控制流与生命周期管理 在现代分布式系统中,控制流与生命周期管理是开发者必须面对的核心挑战之一。Go语言通过context包提供了一种优雅的解决方案,帮助开发者管理请求的取消、超时和跨协程的数据传递。无论是微服务调用、数据库查询还是HTTP…...
GT511C3指纹模块嵌入式驱动开发与工程实践
1. GT511C3指纹识别模块底层驱动技术解析GT511C3是由Digital Persona公司推出的高性能光学指纹识别模块,广泛应用于门禁系统、考勤终端、金融支付设备及嵌入式身份认证场景。该模块基于ARM7TDMI内核主控,集成专用图像处理引擎与模板匹配协处理器…...
OpenClaw技能市场探索:Phi-3-mini-128k-instruct支持的10个实用自动化模块
OpenClaw技能市场探索:Phi-3-mini-128k-instruct支持的10个实用自动化模块 1. 为什么需要技能市场? 第一次接触OpenClaw时,我被它的基础能力惊艳到了——能自动操作我的电脑完成各种任务。但很快发现一个问题:每次都要从头编写指…...
CP853显示驱动库:面向AUTOSAR的车载TFT-LCD底层控制方案
1. CP853 显示驱动库深度解析:面向大众汽车CARIAD平台的TFT-LCD底层控制方案CP853并非通用开源显示库,而是专为大众汽车集团CARIAD软件平台定制开发的嵌入式图形驱动组件。其命名“CP853”隐含硬件型号标识(可能对应某代车载信息娱乐系统SoC集…...
