理解Android WebView的加载流程与事件回调
The following article is from 陆业聪 Author 陆业聪
在Android开发中,WebView用于显示网页和执行JavaScript。理解其加载流程和事件回调对于开发一个功能丰富且用户友好的基于Web的应用至关重要。本文将详细介绍 WebView 加载一个URL时的整个流程和相关的事件回调,帮助开发者更好地掌握其使用方法和处理可能出现的问题。
上面的时序图展示了从开始加载URL到页面加载完成的整个过程中WebView和WebViewClient的交互。每个回调都在特定的时机被触发,以处理不同的事件和状态变化。
2.1 触发加载
if(isNetworkAvailable()) {
webView.loadUrl("http://www.example.com");
} else {
Toast.makeText(context, "Network is unavailable", Toast.LENGTH_LONG).show();
}
public boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
2.2 原生层处理
webView.getSettings().setUserAgentString("CustomUserAgent");
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Uri.parse(url).getHost().equals("www.example.com")) {
// This is my web site, so do not override; let my WebView load the page
return false;
}
// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
});
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
progressBar.setVisibility(View.VISIBLE);
}
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
Log.d("WebView", "Resource Loaded: " + url);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
}
});
2.4 处理特殊事件
webView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(R.string.notification_error_ssl_cert_invalid);
builder.setPositiveButton("continue", (dialog, which) -> handler.proceed());
builder.setNegativeButton("cancel", (dialog, which) -> handler.cancel());
final AlertDialog dialog = builder.create();
dialog.show();
}
});
2.5 页面内容显示
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageCommitVisible(WebView view, String url) {
super.onPageCommitVisible(view, url);
// Perform actions when page is almost visible
Toast.makeText(context, "Page almost visible", Toast.LENGTH_SHORT).show();
}
});
通过这些示例和解决方案,可以更好地理解和利用 WebView 的各种功能。
3.1 主要功能和职责
内容渲染:AwContents 负责将网页内容渲染到 WebView 组件上。它使用 Chromium 的渲染引擎(Blink)来解析 HTML、CSS 和 JavaScript,确保网页内容能够正确显示。 事件处理:它处理来自上层 WebView 和 WebViewClient 的各种事件和请求,如页面加载、资源请求、导航事件等,并将这些事件转发到 Chromium 引擎。 JavaScript 交互:AwContents 提供了与 JavaScript 代码交互的接口,允许 Android 应用与网页中的 JavaScript 代码进行通信。 安全和隐私:它实现了多种安全措施,如同源策略、内容安全策略等,以保护用户的安全和隐私。 网络请求管理:AwContents 管理所有网络请求,包括图片、CSS 文件、JavaScript 文件等资源的加载。它支持自定义网络请求的处理,例如通过 shouldInterceptRequest() 方法拦截和修改请求。
3.2 架构和实现
3.3 使用场景
AwContents 是 Android WebView 中的一个关键组件,它使得 WebView 能够利用 Chromium 引擎的强大功能,提供高性能和高兼容性的网页浏览体验。
4.1 使用onPageStarted和onPageFinished检测加载时间
webView.setWebViewClient(new WebViewClient() {
long startTime;
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
startTime = System.currentTimeMillis();
}
@Override
public 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() {
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
// 处理加载错误
}
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
// 处理HTTP错误
}
});
4.3 使用shouldInterceptRequest监控资源加载
webView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
// 检查请求的资源,记录加载失败的资源
return super.shouldInterceptRequest(view, request);
}
});
4.4 使用onPageCommitVisible
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageCommitVisible(WebView view, String url) {
super.onPageCommitVisible(view, url);
// 检查页面内容是否可见或部分内容是否缺失
view.evaluateJavascript("(function() { return document.getElementById('keyElement').innerHTML; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
if (value == null || value.isEmpty()) {
// 如果关键元素不存在或没有内容,那么可能存在白屏问题
Log.e("WebView", "Key element is missing or empty");
}
}
});
}
});
4.5 结合JavaScript和evaluateJavascript
webView.evaluateJavascript("(function() { return document.body.innerHTML; })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String html) {
if (html.isEmpty()) {
// 处理白屏情况
}
}
});
通过上述方法,结合日志记录和异常处理机制,可以有效地检测和诊断WebView中的白屏问题。这些技术不仅可以帮助开发者提高应用的稳定性和用户体验,还可以在开发和测试阶段快速定位问题。
最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
推荐阅读:
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!