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

embedded/2024/11/13 5:17:16/

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

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

    • 基础配置
    • 加载方式
      • 经常使用
      • 较少遇到
    • 实战场景
    • 所遇问题
      • 加载本地数据报 Not Found...
      • 加载网络资源报 404、500、Not Found... 等

基础配置

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

简化版

 WebView webView = (WebView) findViewById(R.id.webView);WebSettings mWebSettings = webView.getSettings();mWebSettings.setJavaScriptEnabled(true);

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

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

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

通用 xml 布局

<?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"><WebViewandroid: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 文件名)

 webView.loadUrl("file:///android_asset/test.html");

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

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

 webView.loadUrl("https://www.example.com");

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

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

webView.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}
});

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

webView.setWebViewClient(new WebViewClient() {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {view.loadUrl(request.getUrl().toString());return true;}
});

较少遇到

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

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

 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 代码。

 String jsCode = "javascript:alert('Hello, world!');";webView.loadUrl(jsCode);

加载数据并设置基础URL可能类似URL组装效果,未使用过)
使用 loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) 加载HTML字符串,并可以设置基础URL

 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请求加载数据。

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

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


实战场景

本地加载

 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图片文件(未尝试过)

示例全码

package com.example.webviewprojectimport android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivityclass 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.settingswebSettings.cacheMode = WebSettings.LOAD_DEFAULTwebSettings.domStorageEnabled = truewebSettings.javaScriptEnabled = truewebSettings.useWideViewPort = truewebSettings.loadWithOverviewMode = truewebSettings.builtInZoomControls = truewebSettings.displayZoomControls = falsewebSettings.setSupportZoom(false)webSettings.javaScriptCanOpenWindowsAutomatically = truewebSettings.allowFileAccess = truewebSettings.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 = truemWebView.isVerticalScrollBarEnabled = falsemWebView.isHorizontalScrollBarEnabled = falsemWebView.setOnLongClickListener { v: View? -> true }}
}

远程加载

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

 mWebView.loadUrl("http://www.baidu.com");

示例全码

package com.example.webviewprojectimport android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebSettings
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivityclass 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.settingswebSettings.cacheMode = WebSettings.LOAD_DEFAULTwebSettings.domStorageEnabled = truewebSettings.javaScriptEnabled = truewebSettings.useWideViewPort = truewebSettings.loadWithOverviewMode = truewebSettings.builtInZoomControls = truewebSettings.displayZoomControls = falsewebSettings.setSupportZoom(false)webSettings.javaScriptCanOpenWindowsAutomatically = truewebSettings.allowFileAccess = truewebSettings.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 = truemWebView.isVerticalScrollBarEnabled = falsemWebView.isHorizontalScrollBarEnabled = falsemWebView.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的同事看看是否有错误地方,请教请教

http://www.ppmy.cn/embedded/88899.html

相关文章

【kill】Centos/Linux 如何杀死那该死的进程?

简介 系统版本&#xff1a;Centos7.6 kill 命令发送指定的信号到指定的进程或者进程组。如果该信号没有指定&#xff0c;则发送SIGTERM信号&#xff08;15&#xff09;&#xff0c;即终止信号。如果SIGTERM信号&#xff08;15&#xff09;无法终止&#xff0c;可使用SIGKILL&am…

【C++标准模版库】vector的介绍及使用

vector 一.vector的介绍二.vector的使用1.vector 构造函数2.vector 空间增长3.vector 增删查改4.vector 迭代器的使用1.正向迭代器2.反向迭代器 5.victor 迭代器失效问题&#xff08;重点&#xff09; 三.vector不支持 流提取与流插入四.vector存储自定义类型1.存储string2.存储…

关于CSDN登录失效,频繁弹到登录界面

典型特征&#xff1a; 访问其它任何网站都没问题&#xff0c;就是访问任何一个和CSDN有关的网页都会弹到登录界面&#xff0c;且提示认证失败或者Cookies失效等。 刚才我照旧打开CSDN时&#xff0c;CSDN弹出重定向失败&#xff0c;提到了Cookies问题&#xff0c;在个人中心也弹…

Spring学习笔记1

今天内容:配置maven 搭建了springboot项目 约定大于配置&#xff08;它默认的框架优先级比配置的要高&#xff0c;基本全都用它所默认的框架只有特殊需求的时候才会修改一小部分。&#xff09; IOC Spring IOC 管理项目中java bean的生命周期 在项目运行阶段&#xff0c;…

一文带你掌握C++模版

12. C模板 什么是模板 模板编程也可以叫做泛型编程&#xff0c;忽略数据类型的一种编程方式 //求最值问题 int Max(int a,int b) {return a>b?a:b; } double Max(int a,int b) {return a>b?a:b; } string Max(string a,string b) {return a>b?a:b; …

SQLite基础:数据库和表

数据库 1. 创建数据库2. 附加数据库3. 分离数据库4. 创建表5. 删除表 1. 创建数据库 sqlite3 DatabaseName.db注意&#xff1a; 数据库名称在 RDBMS 中应该是唯一的。sqlite3 命令&#xff1a; sqlite3 命令用于创建数据库。但是&#xff0c;如果数据库不存在&#xff0c;则会…

java之方法引用 —— ::

目录 一、简介 二、引用静态方法 1.格式 2.示例 ​编辑 3.条件解析 三、引用成员方法 1.格式 2.示例 四、引用构造方法 1.格式 2.示例 五、类名引用成员方法 1.格式 2.略微不同的方法引用规则 3.示例 六、引用数组的构造方法 1.格式 2.示例 一、简介 方…

第三章 转折13 反馈的重要性

前面讲过“分享串烧”的团队学习分享活动&#xff0c;每周一次&#xff0c;到本周已经举办了4次了&#xff0c;团队的4位同学进行了分享&#xff0c;本周的周会中&#xff0c;我组织大家对这4位同学的分享做了一个小结&#xff0c;让每个人对分享给出积极性和建设性的反馈。 大…