Android入门之路 - WebView加载数据的几种方式

之前客户端加载H5时遇到了一些问题,我为了方便解决问题,所以将对应场景复刻到了Demo中,从之前的网络加载模拟为了本地加载Html的方式,但是没想到无意被一个基础知识点卡了一些时间,翻看往昔笔记发现未曾记录这种基础场景,故补不足,记录于此

关于 WebView 加载数据的几种方式,可以算是基础内容,相信大家都耳熟于心了,直接开讲

基础配置

关于 WebView 基础配置 主要是对 WebSettings 相关属性的设置

简化版

kotlin 复制代码
 WebView webView = (WebView) findViewById(R.id.webView);
 WebSettings mWebSettings = webView.getSettings();
 mWebSettings.setJavaScriptEnabled(true);

因为后续我们需要加载网络资源,所以有必要 添加一下网络权限

Tip :如果仅加载本地资源,可不添加该权限... 但一个项目中不可能没有 INTERNET权限

kotlin 复制代码
 <uses-permission android:name="android.permission.INTERNET" />

通用 xml 布局

html 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

加载方式

关于以下所有方式有的是经常使用的,也有的很少使用,当然还有一些我基本都没用过,没想到AI直接一起归总了,故我整合解释了一下,希望对你我有所帮助

WebView 加载数据的方式很多,但是我从业以来 用的最多的还是本地加载和网络加载,所以这也是我们主讲的内容,关于其他加载方式先做记录,以后如果我遇到了类似场景再来补充实战感受

经常使用

插一句:在项目中有些富文本的样式也可以通过 Html实现,如果主要是看WebView,请忽略此句

本地加载 (加载本地 html文件)- 项目中会遇到一些组件需要固定的数据,有的成品数据就是html文件,所以有时候会用到这种方式

使用 loadUrl(String path) 方法加载本地文件,如 file:///android_asset/test.html(自行定义html 文件名)

java 复制代码
 webView.loadUrl("file:///android_asset/test.html");

网络加载 (加载H5的URL)- 主流方式,项目中基本90%都用这种方式

使用 loadUrl(String url) 方法加载网络或本地文件的URL

java 复制代码
 webView.loadUrl("https://www.example.com");

WebView 实际使用中,我们经常会通过 WebViewClient 监听一些加载情况,以下是比较常用的两个重载监听方法

通过设置 WebViewClient 并重写 shouldOverrideUrlLoading 方法来控制URL加载行为

java 复制代码
webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
});

使用 WebResourceRequest:在Android N(API 24)及以上版本,可以在 WebViewClient 中重写 shouldOverrideUrlLoading 方法的重载版本,接收 WebResourceRequest 参数

java 复制代码
webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        view.loadUrl(request.getUrl().toString());
        return true;
    }
});

较少遇到

加载HTML字符串感觉这种方式相当于把html文件提到了代码内部,如果html比较多的话,可能不太适用

使用 loadData(String data, String mimeType, String encoding) 方法加载HTML字符串

java 复制代码
 String htmlData = "<html><head><title>Page Title</title></head><body>Hi, WebView!</body></html>";
 webView.loadData(htmlData, "text/html; charset=UTF-8", "UTF-8");

加载JavaScript代码 (双端交互时调用H5的Js方法,前提的和H5确定过交互需求,否则无效,且有可能报错)

使用 loadUrl(String js) 方法执行 JavaScript 代码。

java 复制代码
 String jsCode = "javascript:alert('Hello, world!');";
 webView.loadUrl(jsCode);

加载数据并设置基础URL可能类似URL组装效果,未使用过)

使用 loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) 加载HTML字符串,并可以设置基础URL

java 复制代码
 String baseUrl = "https://www.example.com";
 String htmlData = "<html>...</html>";
 webView.loadDataWithBaseURL(baseUrl, htmlData, "text/html", "UTF-8", null);

加载POST请求数据可能类似URL组装效果,未使用过)

使用 postUrl(String url, byte[] postData) 方法通过POST请求加载数据。

java 复制代码
 String url = "https://www.example.com/post";
 byte[] postData = ...; // 你的POST数据
 webView.postUrl(url, postData);

加载XML或HTML文件 :可以将其作为字符串加载,然后解析(未见过该类需求,未使用过


实战场景

本地加载

kotlin 复制代码
 WebView mWebView = (WebView) findViewById(R.id.wv1);
 WebSettings mWebSettings = mWebView.getSettings();
 mWebSettings.setJavaScriptEnabled(true);
 mWebView.loadUrl("file:///android_asset/test.html");//工程目录assets test.html文件
 
 mWebView.loadUrl("file:///android_asset/icon.png");//工程目录assets图片文件(未尝试过)

示例全码

kotlin 复制代码
package com.example.webviewproject

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private val mWebView: WebView by lazy {
        findViewById<WebView>(R.id.webView)
    }

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initWebView(mWebView)
        //加载本地资源
        mWebView.loadUrl("file:///android_asset/test.html");
//        mWebView.loadUrl("file:///android_asset/web/test.html")
    }

    /**
    * 初始化WebSettings配置
    * */
    private fun initWebView(mWebView: WebView) {
        mWebView.clearCache(true)
        mWebView.clearHistory()
        val webSettings = mWebView.settings
        webSettings.cacheMode = WebSettings.LOAD_DEFAULT
        webSettings.domStorageEnabled = true
        webSettings.javaScriptEnabled = true
        webSettings.useWideViewPort = true
        webSettings.loadWithOverviewMode = true
        webSettings.builtInZoomControls = true
        webSettings.displayZoomControls = false
        webSettings.setSupportZoom(false)
        webSettings.javaScriptCanOpenWindowsAutomatically = true
        webSettings.allowFileAccess = true
        webSettings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS
//        webSettings.setAppCacheEnabled(true);
//        webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
//        webSettings.setAppCachePath(this.getApplicationContext().getCacheDir().getAbsolutePath());
//        webSettings.setUserAgentString(webSettings.getUserAgentString() + " ECTASR/1");
//        mWebView.setWebChromeClient(new CustomerActivity.WebChromeClient());
//        mWebView.webViewClient = WebViewClient()
        mWebView.isFocusable = true
        mWebView.isVerticalScrollBarEnabled = false
        mWebView.isHorizontalScrollBarEnabled = false
        mWebView.setOnLongClickListener { v: View? -> true }
    }
}

远程加载

相比加载本地文件,远程加载 url 除了添加授权和加载数据源不同之外,示例层面没变动,主要还是功能方面有了更多的可能性和交互性

kotlin 复制代码
 mWebView.loadUrl("http://www.baidu.com");

示例全码

kotlin 复制代码
package com.example.webviewproject

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private val mWebView: WebView by lazy {
        findViewById<WebView>(R.id.webView)
    }

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initWebView(mWebView)
        //加载本地资源
		mWebView.loadUrl("http://www.baidu.com")
    }

    /**
    * 初始化WebSettings配置
    * */
    private fun initWebView(mWebView: WebView) {
        mWebView.clearCache(true)
        mWebView.clearHistory()
        val webSettings = mWebView.settings
        webSettings.cacheMode = WebSettings.LOAD_DEFAULT
        webSettings.domStorageEnabled = true
        webSettings.javaScriptEnabled = true
        webSettings.useWideViewPort = true
        webSettings.loadWithOverviewMode = true
        webSettings.builtInZoomControls = true
        webSettings.displayZoomControls = false
        webSettings.setSupportZoom(false)
        webSettings.javaScriptCanOpenWindowsAutomatically = true
        webSettings.allowFileAccess = true
        webSettings.layoutAlgorithm = WebSettings.LayoutAlgorithm.NARROW_COLUMNS
//        webSettings.setAppCacheEnabled(true);
//        webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
//        webSettings.setAppCachePath(this.getApplicationContext().getCacheDir().getAbsolutePath());
//        webSettings.setUserAgentString(webSettings.getUserAgentString() + " ECTASR/1");
//        mWebView.setWebChromeClient(new CustomerActivity.WebChromeClient());
//        mWebView.webViewClient = WebViewClient()
        mWebView.isFocusable = true
        mWebView.isVerticalScrollBarEnabled = false
        mWebView.isHorizontalScrollBarEnabled = false
        mWebView.setOnLongClickListener { v: View? -> true }
    }
}

所遇问题

加载本地数据报 Not Found...

提前和你说一下,当你遇到这种问题,基本和我一样都是一个粗心的人儿!

  1. 关于 asserts 目录层级要求

关于通过对 WebView 加载本地Html的方式,这么多年来一直没有变过,但是我尝试多次,一直加载失败...

不清楚你是否也遇到了这样粗心的问题?关于存放html的文件需要放置于asserts目录内,而该目录是与 java、res 同级的目录文件,切勿放错了!

  1. 有心的朋友可能注意到了我在本地加载中注释了一行 mWebView.loadUrl("file:///android_asset/web/test.html") ,注意这里加载层级有没有多一层或者少一层之类的? 如下

加载网络资源报 404、500、Not Found... 等

  1. 首先将加载的链接放在游览器看是否可以正常加载?
  2. 是否添加了网络权限?
  3. 是否为https 的url?Android在9.0开始好像对安全有了提升,所以有此要求
  4. 项目中可以看一下另一端是否可正常加载,排除错误场景
  5. 项目中可以找返给你url的同事看看是否有错误地方,请教请教
相关推荐
selt7912 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
Yao_YongChao2 小时前
Android MVI处理副作用(Side Effect)
android·mvi·mvi副作用
非凡ghost3 小时前
JRiver Media Center(媒体管理软件)
android·学习·智能手机·媒体·软件需求
席卷全城3 小时前
Android 推箱子实现(引流文章)
android
齊家治國平天下3 小时前
Android 14 系统中 Tombstone 深度分析与解决指南
android·crash·系统服务·tombstone·android 14
maycho1235 小时前
MATLAB环境下基于双向长短时记忆网络的时间序列预测探索
android
思成不止于此6 小时前
【MySQL 零基础入门】MySQL 函数精讲(二):日期函数与流程控制函数篇
android·数据库·笔记·sql·学习·mysql
brave_zhao6 小时前
达梦数据库(DM8)支持全文索引功能,但并不直接兼容 MySQL 的 FULLTEXT 索引语法
android·adb
sheji34166 小时前
【开题答辩全过程】以 基于Android的网上订餐系统为例,包含答辩的问题和答案
android
easyboot7 小时前
C#使用SqlSugar操作mysql数据库
android·sqlsugar