Android WebView 从入门到最佳实践

WebView 是什么?

WebView = 嵌在 App 内的浏览器

基于系统 Chromium 引擎,可渲染 HTML / CSS / JavaScript / 音视频。

适用业务:

  • H5 页面嵌入(活动页、产品介绍)

  • 混合开发(Hybrid)

  • 支付与登录授权页面

  • 文档/文章加载展示

WebView 整体架构

复制代码
┌───────────────────────────┐
│          WebView          │ ← 容器(渲染网页)
├───────────────────────────┤
│   WebViewClient           │ ← 加载/navigation 控制(内开/外跳/拦截)
├───────────────────────────┤
│   WebChromeClient         │ ← UI & 权限(进度、标题、上传、全屏)
└───────────────────────────┘

WebView负责显示

WebViewClient负责怎么加载(路由/网络)

WebChromeClient负责展示浏览器 UI & 权限

WebSettings:浏览器能力开关

Kotlin 复制代码
webView.settings.apply {
    javaScriptEnabled = true          // 必开(否则大多数 H5 白屏)
    domStorageEnabled = true          // 支持 localStorage / sessionStorage
    useWideViewPort = true            // 页面自适应
    loadWithOverviewMode = true
    cacheMode = WebSettings.LOAD_DEFAULT
}
CookieManager.getInstance().setAcceptCookie(true)

常用开关:

功能 设置
是否允许 JS javaScriptEnabled
LocalStorage/IndexedDB domStorageEnabled
混合内容(HTTPS + HTTP) mixedContentMode
自动播放视频 mediaPlaybackRequiresUserGesture = false

WebViewClient:控制页面"怎么打开"

职责:网络/导航/资源/错误控制

能力 方法
点击链接是否内开/外跳 shouldOverrideUrlLoading
页面生命周期 onPageStarted/onPageFinished
拦截资源请求 shouldInterceptRequest
错误处理 onReceivedError
SSL 证书错误 onReceivedSslError

⚠️ 没设置 WebViewClient → 点击链接会跳系统浏览器

Kotlin 复制代码
webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(v: WebView, r: WebResourceRequest): Boolean {
        val url = r.url.toString()
        return if (url.startsWith("http")) false
        else { startActivity(Intent(Intent.ACTION_VIEW, r.url)); true }
    }
}

return false = WebView 内开
return true = 你处理(常见:跳外部 App,如微信/支付宝)

WebChromeClient:UI / 权限 / 上传

职责:浏览器 UI 和用户交互

功能 方法
进度条 onProgressChanged
网页标题 onReceivedTitle
JS 的 alert/confirm/prompt onJsAlert/onJsConfirm
上传图片 / 文件 onShowFileChooser
相机/麦克风权限 onPermissionRequest
视频全屏播放 onShowCustomView

示例(显示进度条):

Kotlin 复制代码
webView.webChromeClient = object : WebChromeClient() {
    override fun onProgressChanged(view: WebView, newProgress: Int) {
        progressBar.progress = newProgress
    }
}

文件上传、视频全屏、相机权限 都属于 WebChromeClient,不属于 WebViewClient。

JS ↔ Android 互调(JS Bridge)

✅ JS 调 Android(H5 调原生)

Kotlin 复制代码
class JsBridge {
    @JavascriptInterface
    fun toast(msg: String){ Toast.makeText(context, msg, Toast.LENGTH_SHORT).show() }
}
webView.addJavascriptInterface(JsBridge(), "Android")

JS 调用Android:

复制代码
Android.toast("Hello WebView") 

Android 调 JS :

Kotlin 复制代码
webView.evaluateJavascript("javascript:showDialog()") {}

离线包 / 本地资源加载(关键能力)

安全加载本地 H5,不用 file://

Kotlin 复制代码
val loader = WebViewAssetLoader.Builder()
    .addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(this))
    .build()

override fun shouldInterceptRequest(v: WebView, r: WebResourceRequest) =
    loader.shouldInterceptRequest(r.url)

H5 访问:

https://appassets.androidplatform.net/assets/index.html
WebViewAssetLoader = 最安全的离线包方案(支持 HTTPS,同源策略不会报错)


Kotlin 复制代码
val cm = CookieManager.getInstance()
cm.setAcceptCookie(true)
cm.setAcceptThirdPartyCookies(webView, true)

若不设置第三方 Cookie → 支付/登录无法回跳

WebView 销毁防止内存泄漏(必须写)

Kotlin 复制代码
override fun onDestroy() {
    (webView.parent as ViewGroup).removeView(webView)
    webView.stopLoading()
    webView.clearHistory()
    webView.removeAllViews()
    webView.destroy()
    super.onDestroy()
}

常见问题处理(实战)

问题 原因 解决方案
点击链接跳系统浏览器 没设置 WebViewClient 添加 shouldOverrideUrlLoading
上传图片没反应 没设置 WebChromeClient onShowFileChooser
JS 调原生不生效 未添加 @JavascriptInterface 加注释
H5 页面白屏 JavaScript 未开启 javaScriptEnabled = true
微信/支付宝不能回跳 Cookie 未开启第三方 setAcceptThirdPartyCookies

最终总结

模块 作用
WebSettings 开关能力(JS、缓存、localStorage)
WebViewClient 控制网络行为(内开/外跳、拦截资源、错误处理)
WebChromeClient UI 与权限(进度条、标题、上传、全屏视频)
JS Bridge JS 与原生互调
CookieManager 登录状态维持
WebViewAssetLoader 离线包

一句话记住:

WebViewControl = WebView + WebViewClient + WebChromeClient

下一篇:

WebView 最佳封装模板(BaseWebActivity + WebViewHelper)

相关推荐
e***58234 小时前
Spring Cloud GateWay搭建
android·前端·后端
x***13397 小时前
【MyBatisPlus】MyBatisPlus介绍与使用
android·前端·后端
n***54388 小时前
【MySQL】MySQL内置函数--日期函数字符串函数数学函数其他相关函数
android·mysql·adb
z***751510 小时前
【Springboot3+vue3】从零到一搭建Springboot3+vue3前后端分离项目之后端环境搭建
android·前端·后端
程序员陆业聪10 小时前
Android模拟器检测全面指南:从基础到高级策略
android
2501_9160088911 小时前
iOS 性能测试的深度实战方法 构建从底层指标到真实场景回放的多工具测试体系
android·ios·小程序·https·uni-app·iphone·webview
w***954911 小时前
SQL美化器:sql-beautify安装与配置完全指南
android·前端·后端
r***123812 小时前
若依微服务中配置 MySQL + DM 多数据源
android·mysql·微服务
ALex_zry12 小时前
MySQL连接数管理与优化实操经验分享
android·mysql·adb
apigfly14 小时前
深入Android系统(十三)Android的窗口系统
android·设计模式·源码