Android语言基础教程(253)Android使用WebView显示网页之使用WebView加载HTML代码:别翻了!让你的APP秒变“浏览器”,WebView加载HTML的骚操作全在这儿了

一、开篇:为什么你的APP需要“体内消化”网页?

大家好,我是码农老李,今天咱们聊个有意思的话题——用WebView在APP里加载HTML代码。你肯定遇到过这种场景:产品经理笑眯眯地凑过来说:“这个活动页用H5实现吧,方便迭代~” 然后你默默打开浏览器,看着密密麻麻的网页代码,思考人生三连:

  1. 难道要让用户跳转到浏览器?
  2. 体验割裂被骂怎么办?
  3. 如何优雅地“偷懒”?

别急,WebView就是你的“梦中情View”!它就像给APP塞了个迷你浏览器,既能直接显示网页,又能加载本地HTML代码。比如你收到后端甩来的一段富文本:“<h1>限时抢购</h1><p>点击就送<span style="color:red">SSR</span></p>”,用WebView就能轻松渲染成漂亮页面!

举个栗子�*:
某电商APP的商品详情页,上半部分是原生开发的图片轮播,下半部分直接用WebView展示商品介绍的HTML内容——这种“杂交”模式,既保留了原生流畅性,又享受了H5的灵活更新。


二、WebView初体验:从“Hello World”开始翻车
2.1 基础配置三连击

首先,别忘记给APP“开权限”!在AndroidManifest.xml加上网络权限(虽然加载本地HTML不需要,但加载在线资源时必备):

<uses-permission android:name="android.permission.INTERNET" />

接着在布局文件里塞入WebView控件:

<WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

最后在Activity里搞点事情:

val webView = findViewById<WebView>(R.id.webview)
webView.loadUrl("https://www.baidu.com") // 经典操作

但是! 如果你直接这么写,很可能遇到两大经典翻车现场:

  • 页面打开默认跳转系统浏览器(用户:我APP呢?)
  • 加载http链接报错(Android 9以后默认禁止明文传输)

解决方案:

// 阻止跳转外部浏览器
webView.webViewClient = WebViewClient()

// 允许http链接(如果需要)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
}
2.2 加载HTML的三种骚操作

方式一:直接加载HTML代码(重点!)
当你拿到一段HTML字符串时,可以这样搞:

val html = """
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
            body { background: #f0f0f0; }
            .highlight { color: red; }
        </style>
    </head>
    <body>
        <h1>我是本地HTML</h1>
        <p class="highlight">红色重点内容</p>
        <img src="https://example.com/image.jpg">
    </body>
    </html>
""".trimIndent()

webView.loadData(html, "text/html", "UTF-8")

注意坑位:如果HTML里包含特殊字符(比如#、%等),需要用loadDataWithBaseURL

webView.loadDataWithBaseURL(
    null, // 基础URL,用于解析相对路径
    html,
    "text/html", 
    "UTF-8", 
    null // 历史记录URL,一般传null
)

方式二:加载assets里的HTML文件
把HTML文件扔进app/src/main/assets文件夹,然后:

webView.loadUrl("file:///android_asset/local_page.html")

方式三:加载手机存储的HTML文件

webView.loadUrl("content://com.example.provider/local.html") // 需要ContentProvider

三、进阶玩法:让WebView变成“智能助理”
3.1 与JavaScript互相调情

想要WebView执行JS代码?先开启设置:

webView.settings.javaScriptEnabled = true

然后就可以愉快地调教JS了:

// 调用JS方法
webView.evaluateJavascript("javascript:showToast('Hello')") { result ->
    // 处理JS返回值
}

// 让JS调用Java方法
webView.addJavascriptInterface(object {
    @JavascriptInterface
    fun nativeMethod(param: String) {
        runOnUiThread { 
            Toast.makeText(this, "JS传参:$param", Toast.LENGTH_SHORT).show()
        }
    }
}, "AndroidBridge")

在HTML中这样调用:

<button onclick="window.AndroidBridge.nativeMethod('我是前端')">调用原生方法</button>
3.2 拦截页面请求实现“暗箱操作”

通过重写shouldOverrideUrlLoading,可以监听页面跳转:

webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
        val url = request.url.toString()
        if (url.contains("special://scheme")) {
            // 拦截特定scheme,执行原生逻辑
            handleSpecialScheme(url)
            return true // 表示已处理,不继续加载
        }
        return false // 继续加载
    }
}
3.3 性能优化:从“拖拉机”到“超跑”

开启缓存(避免重复加载):

webView.settings.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
webView.settings.domStorageEnabled = true // 开启DOM存储

懒加载图片

webView.settings.loadsImagesAutomatically = false // 禁止自动加载图片
// 在页面完成后手动加载图片
webView.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView, url: String) {
        view.evaluateJavascript("document.images[0].src = document.images[0].getAttribute('data-src')") { }
    }
}

四、避坑指南:那些年我们踩过的雷
4.1 安全漏洞三件套

漏洞一:任意命令执行
错误示范❌:

webView.addJavascriptInterface(someObject, "bridge") // 4.2以下系统有风险

正确姿势✅:

  • 仅对Android 4.2以上系统使用@JavascriptInterface注解
  • 或使用evaluateJavascript替代

漏洞二:明文传输
在AndroidManifest.xml中给Application添加:

android:usesCleartextTraffic="true"

(但更推荐全站HTTPS)

漏洞三:域控制不严
通过WebViewClientonReceivedSslError处理SSL错误时,不要总是proceed!

4.2 内存泄漏终结方案

在Activity销毁时记得清理:

override fun onDestroy() {
    webView?.apply {
        loadDataWithBaseURL(null, "", "text/html", "utf-8", null)
        clearHistory()
        (parent as? ViewGroup)?.removeView(this)
        destroy()
    }
    super.onDestroy()
}
4.3 加载进度条实现
// 在布局中加入ProgressBar
webView.webChromeClient = object : WebChromeClient() {
    override fun onProgressChanged(view: WebView, newProgress: Int) {
        progressBar.progress = newProgress
        if (newProgress == 100) progressBar.visibility = View.GONE
    }
}

五、实战:打造一个富文本显示器

假设你要实现一个新闻详情页,后端返回的HTML可能包含视频、表格等复杂内容:

fun setupRichTextWebView(htmlContent: String) {
    val styledHtml = """
        <!DOCTYPE html>
        <html>
        <head>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <style>
                body { 
                    font-family: 'San Francisco';
                    line-height: 1.6;
                    padding: 20px;
                }
                img { max-width: 100%; height: auto; }
                video { max-width: 100%; }
                table { width: 100%; border-collapse: collapse; }
                td, th { border: 1px solid #ddd; padding: 8px; }
            </style>
        </head>
        <body>
            $htmlContent
        </body>
        </html>
    """.trimIndent()
    
    webView.apply {
        settings.let { s ->
            s.javaScriptEnabled = true
            s.loadWithOverviewMode = true
            s.useWideViewPort = true
            s.setSupportZoom(true)
        }
        loadDataWithBaseURL(null, styledHtml, "text/html", "UTF-8", null)
    }
}

六、结语:WebView虽好,可不要贪杯哦

WebView就像APP开发的“瑞士军刀”——功能强大但需要谨慎使用。记住几个关键点:

  • 简单展示loadData复杂页面loadDataWithBaseURL
  • 必设WebViewClient,防止跳转外部浏览器
  • 安全配置要到位,避免被黑客钻空子
  • 内存管理不能忘,否则APP变卡顿怪兽

最后送大家一句口诀:“权限客户端,缓存加安全,交互靠JS,销毁要彻底”。掌握了WebView,下次产品经理再提H5需求时,你可以优雅地回一句:“安排!”

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值