当前位置: 首页 > news >正文

Flutter笔记:关于WebView插件的用法(上)

Flutter笔记
关于WebView插件的用法(上)

- 文章信息 - Author: 李俊才 (jcLee95)
Visit me at CSDN: https://jclee95.blog.csdn.net
My WebSitehttp://thispage.tech/
Email: 291148484@163.com.
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/138754747
HuaWei:https://bbs.huaweicloud.com/blogs/428876

【介绍】:WebView是一个可以在移动应用中显示网页的组件。它基于原生的WebView控件(如iOS中的WKWebView和Android中的WebView),提供了加载URL、显示HTML内容、与JavaScript交互等功能。通过在Flutter应用中使用WebView,我们可以方便地集成Web内容,并与之进行交互。本文介绍Flutter中WebView插件的用法。

flutter-ljc


下一节:《 关于WebView插件的用法(下)


1. 概述与用法入门

1.1 Flutter WebView简介

Flutter应用中,我们经常需要展示网页内容或者与Web进行交互。WebView插件提供了在Flutter应用中嵌入和控制Web内容的能力。WebView是一个可以在移动应用中显示网页的组件。它基于原生的WebView控件(如iOS中的WKWebViewAndroid中的WebView),提供了加载URL、显示HTML内容、与JavaScript交互等功能。通过在Flutter应用中使用WebView,我们可以方便地集成Web内容,并与之进行交互。

要在Flutter应用中使用WebView组件,首先需要创建一个WebViewController实例来管理WebView的各种行为和属性。然后将WebViewController对象传递给WebViewWidget以在界面上显示WebView内容。

FlutterWebView插件(webview_flutter)是官方提供的一个用于在Flutter应用中嵌入WebView的插件。它封装了原生的WebView控件,并提供了一套统一的Dart API,使得在Flutter中使用WebView变得简单和高效。

1.2 webview_flutter库的安装

要在Flutter项目中使用WebView插件,首先需要在pubspec.yaml文件中添加webview_flutter库的依赖。打开pubspec.yaml文件,在dependencies部分添加如下内容:

dependencies:flutter:sdk: flutterwebview_flutter: ^4.8.0

这里我们指定了webview_flutter库的版本号为4.8.0,这是目前最新的稳定版本。你可以根据需要选择适合你项目的版本。添加完依赖后,获取库文件:

flutter pub get

这会下载webview_flutter库及其相关的依赖项,并将其添加到项目中。

如果你希望直接使用最新版本添加到项目中,也可以:

flutter pub add webview_flutter

对于Android平台,webview_flutter库需要Android SDK版本19或更高版本的支持,还需要在android/app/build.gradle文件中将最低SDK版本设置为19或更高:

android {defaultConfig {// ...minSdkVersion 19}
}

另外,在安卓平台使用WebView加载网页时,多数情况下都需要用到网络,需要确保你的应用有访问网络的权限。对于Android平台,需要在AndroidManifest.xml文件中添加以下权限:

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

对于iOS平台,需要在ios/Runner/Info.plist文件中添加以下键值对,以允许WebView加载HTTP内容:

<key>NSAppTransportSecurity</key>
<dict><key>NSAllowsArbitraryLoads</key><true/>
</dict>

这个配置允许WebViewiOS 9及更高版本中加载任意的HTTP内容。如果你的应用只需要加载HTTPS内容,可以忽略这个配置。

1.3 WebViewController的创建和生命周期

在使用WebView之前,需要先创建一个WebViewController对象。可以直接通过WebViewController的构造函数来创建实例:

final WebViewController controller = WebViewController();

这将创建一个默认配置的WebViewController实例。

你也可以在创建时直接设置一些初始参数,例如:

final WebViewController controller = WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted)..setBackgroundColor(const Color(0x00000000))..setNavigationDelegate(NavigationDelegate(onProgress: (int progress) {// 页面加载进度变化时会调用},onPageStarted: (String url) {// 页面开始加载时调用},onPageFinished: (String url) {// 页面加载完成时调用},onWebResourceError: (WebResourceError error) {// 页面加载出错时调用},),)..loadRequest(Uri.parse('https://flutter.dev'));

以上代码创建了一个WebViewController,并设置了JavaScript执行模式、背景颜色、导航代理以及初始加载的URL

1.4 设置WebView属性

创建完WebViewController实例后,可以根据需要设置WebView的各种属性,例如:

1.4.1 JavaScript执行模式

controller.setJavaScriptMode(JavaScriptMode.unrestricted);

通过setJavaScriptMode方法可以设置页面中JavaScript的执行模式,可选值包括:

  • JavaScriptMode.disabled: 不允许执行JavaScript

  • JavaScriptMode.unrestricted: 允许执行JavaScript,不做任何限制。

1.4.2 背景颜色

controller.setBackgroundColor(const Color(0x00000000));

使用setBackgroundColor方法可以为WebView设置背景颜色。上面的代码将背景色设为透明。

1.4.3 用户代理

用户代理的概念

用户代理(User Agent)是一个字符串,用于标识浏览器或客户端的身份和版本信息。它是HTTP请求头中的一个字段,服务器可以通过解析用户代理字符串来了解发起请求的客户端的相关信息。

用户代理字符串通常包含以下几个部分:

  1. 浏览器或客户端的名称和版本号,如**“Mozilla/5.0”、“Chrome/93.0.4577.82”**等。
  2. 操作系统的名称和版本号,如"Windows NT 10.0"、"Android 11"等。
  3. 渲染引擎的名称和版本号,如**“AppleWebKit/537.36”“Gecko/20100101”**等。
  4. 其他一些标识信息,如设备型号、语言等。

下面是一个典型的用户代理字符串的示例:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36

这个用户代理字符串表示:

  • 浏览器名称和版本号:Chrome/93.0.4577.82

  • 操作系统:Windows NT 10.0 (64位)

  • 渲染引擎:AppleWebKit/537.36 (兼容KHTML和Gecko)

  • 其他标识:Safari/537.36 (表示兼容Safari浏览器)

服务器可以根据用户代理字符串来判断客户端的类型和版本,从而提供不同的内容或功能。例如,某些网站可能会根据用户代理判断是桌面浏览器还是移动浏览器,从而返回不同的页面布局

WebView中,默认使用系统提供的用户代理字符串,表示当前WebView所在的平台和版本信息。但有时我们可能需要自定义用户代理字符串,以模拟特定的浏览器或客户端,或者向服务器传递额外的信息。

通过自定义用户代理字符串,可以改变WebView在发送HTTP请求时所携带的用户代理信息,从而影响服务器的响应和行为。这在某些特定场景下可能会很有用,如兼容性测试、数据爬取等。

设置用户代理
controller.setUserAgent('Custom UA String');

通过setUserAgent方法可以自定义WebView的用户代理字符串。

1.2.4 导航代理

controller.setNavigationDelegate(NavigationDelegate(onProgress: (int progress) {// 页面加载进度变化时会调用},onPageStarted: (String url) {// 页面开始加载时调用},onPageFinished: (String url) {// 页面加载完成时调用},onWebResourceError: (WebResourceError error) {// 页面加载出错时调用},
));

通过setNavigationDelegate方法可以设置一个NavigationDelegate对象,它可以监听页面加载过程中的各种事件,包括:

  • onProgress: 页面加载进度变化时调用。

  • onPageStarted: 页面开始加载时调用。

  • onPageFinished: 页面加载完成时调用。

  • onWebResourceError: 页面加载出错时调用。

除了上述常用的属性外,WebViewController还提供了其他一些方法来控制WebView的行为,如:

  • clearCache: 清除WebView的缓存数据。

  • clearLocalStorage: 清除WebView的本地存储数据。

  • goBack: 后退到上一页。

  • goForward: 前进到下一页。

  • reload: 重新加载当前页面。

  • runJavaScript: 在页面中执行JavaScript代码。

  • runJavaScriptReturningResult: 在页面中执行JavaScript代码,并获取返回值。

  • addJavaScriptChannel: 注册JavaScript通道,以便页面可以向Flutter发送消息。

你可以根据实际需求,调用这些方法来控制WebView的行为和功能。

通过设置WebViewController的各种属性和方法,你可以对WebView的表现进行灵活的控制和定制。在后续的小节中,我们还会详细介绍更多的WebView使用技巧和场景。

1.5 加载网页

在创建并配置好WebViewController后,可以使用其loadRequest方法来加载指定URL的网页。例如:

final WebViewController controller = WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted)..setBackgroundColor(const Color(0x00000000))..setNavigationDelegate(NavigationDelegate(// ...))..loadRequest(Uri.parse('https://flutter.dev'));

上面的代码在创建WebViewController实例后,通过级联操作符(..)直接调用了loadRequest方法,传入了要加载的URL。

loadRequest方法接受一个Uri对象作为参数,表示要加载的网页URL。你可以使用Uri.parse方法将URL字符串解析为Uri对象。

除了直接传入URL外,loadRequest方法还支持其他一些可选参数:

  • method: HTTP请求方法,默认为LoadRequestMethod.get,表示使用GET方法请求。你可以传入LoadRequestMethod.post来发送POST请求。

  • headers: HTTP请求头,默认为空。你可以传入一个Map<String, String>对象来设置自定义的请求头。

  • body: 请求体数据,默认为null。对于POST请求,你可以传入一个Uint8List对象作为请求体。

例如,发送一个POST请求并设置自定义请求头:

controller.loadRequest(Uri.parse('https://example.com/api/endpoint'),method: LoadRequestMethod.post,headers: <String, String>{'Content-Type': 'application/json'},body: Uint8List.fromList('{"key": "value"}'.codeUnits),
);

通过使用loadRequest方法,你可以灵活地加载各种URL的网页,并根据需要设置请求方法、请求头和请求体等参数。

1.6 显示WebView组件

在Flutter页面中显示WebView内容非常简单,只需要将之前创建的WebViewController实例传递给WebViewWidget即可。


Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('WebView示例'),),body: WebViewWidget(controller: controller,),);
}

上面的代码在Scaffoldbody属性中使用了WebViewWidget,并将之前创建的WebViewController实例controller传递给了它的controller参数。

这样,WebView的内容就会显示在页面的主体部分。你可以根据需要调整WebViewWidget的位置和大小,例如可以将其放在ColumnRowStack等布局组件中。

需要注意的是,WebViewWidget的父组件必须提供一个非空的BuildContext,因此通常将其放在StatefulWidgetbuild方法中。

另外,如果要在WebView中显示的内容需要访问网络,别忘了在应用的AndroidManifest.xml文件中添加网络权限:

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

对于iOS,默认就已经包含了网络访问权限,无需额外配置。

通过将WebViewController传递给WebViewWidget,并将其放置在页面的合适位置,你就可以在Flutter应用中方便地显示WebView内容了。

以上就是WebView的基本用法,包括创建WebViewController、设置WebView属性、加载网页以及在页面中显示WebView组件。掌握了这些基础知识后,你就可以开始在Flutter应用中集成和使用WebView功能了。

在后续的小节中,我们还会介绍更多WebView的进阶用法和技巧,如导航控制、JavaScript交互、页面加载事件处理等。

2. 导航控制

WebView提供了一些方法来控制页面的导航,包括跳转到新的URL、前进、后退等操作。下面我们来详细介绍这些导航控制的用法。

2.1 页面跳转

WebView中,可以使用WebViewControllerloadRequest方法来跳转到新的URL。该方法接受一个Uri对象作为参数,表示要加载的目标URL

例如,要跳转到Flutter官网,可以这样调用loadRequest方法:

controller.loadRequest(Uri.parse('https://flutter.dev'));

除了直接传入URL字符串外,loadRequest方法还支持其他一些可选参数:

  • method: HTTP请求方法,默认为 LoadRequestMethod.get,表示使用 GET方法请求。你可以传入LoadRequestMethod.post来发送 POST请求。

  • headers: HTTP请求头,默认为空。你可以传入一个**Map<String, String>**对象来设置自定义的请求头。

  • body: 请求体数据,默认为null。对于 POST 请求,你可以传入一个 Uint8List 对象作为请求体。

例如,发送一个 POST 请求并设置自定义请求头:

controller.loadRequest(Uri.parse('https://example.com/api/endpoint'),method: LoadRequestMethod.post,headers: <String, String>{'Content-Type': 'application/json'},body: Uint8List.fromList('{"key": "value"}'.codeUnits),
);

通过使用loadRequest方法,你可以灵活地加载各种URL的网页,并根据需要设置请求方法、请求头和请求体等参数。

2.2 页面前进后退

WebView维护了一个页面历史栈,可以通过调用WebViewControllergoBackgoForward方法来实现页面的前进和后退操作。

  • goBack:后退到上一页,相当于浏览器的后退按钮;
  • goForward:前进到下一页,相当于浏览器的前进按钮。

例如,在WebView中后退到上一页:

controller.goBack();

WebView中前进到下一页:

controller.goForward();

你可以根据需要在合适的时机调用这些方法,例如在用户点击后退或前进按钮时执行相应的操作。此外,WebViewController还提供了一些与导航历史相关的方法:

  • canGoBack:返回一个Future<bool>,表示当前是否可以执行后退操作。
  • canGoForward:返回一个Future<bool>,表示当前是否可以执行前进操作。
  • currentUrl:返回一个Future<String>,表示当前页面的URL

你可以使用这些方法来检查导航历史的状态,并根据需要更新界面上的导航按钮等元素。例如:

// 检查是否可以后退
controller.canGoBack().then((bool canGoBack) {if (canGoBack) {// 更新后退按钮的状态,使其可用} else {// 更新后退按钮的状态,使其不可用}
});
// 获取当前页面的URL
controller.currentUrl().then((String url) {// 更新界面上显示的URL
});

通过合理使用WebViewController提供的导航控制方法,你可以实现类似浏览器的前进、后退等功能,提供更好的用户体验。

2.3 页面重载

WebView中,可以通过调用WebViewControllerreload方法来重新加载当前页面。这个操作相当于浏览器中的刷新按钮,会重新请求并加载当前页面的内容。

示例代码:

// 重新加载当前页面
controller.reload();

你可以在需要的时候调用reload方法,例如在用户点击刷新按钮时执行重新加载操作:

FloatingActionButton(onPressed: () {// 重新加载当前页面controller.reload();},child: const Icon(Icons.refresh),
),

通过调用reload方法,WebView会重新发起请求,获取并加载当前页面的最新内容。这对于需要更新页面数据或者重试加载失败的页面非常有用。

2.4 导航请求拦截

WebView在加载新页面时,会触发导航请求。通过设置WebViewControllernavigationDelegate属性,可以拦截并处理这些导航请求,决定是否允许页面跳转。例如:

controller.setNavigationDelegate(NavigationDelegate(// 导航请求回调onNavigationRequest: (NavigationRequest request) {// 判断请求的URL是否符合条件if (request.url.startsWith('https://example.com/')) {// 允许跳转到指定域名的页面return NavigationDecision.navigate;} else {// 阻止跳转到其他域名的页面return NavigationDecision.prevent;}},
));

在上面的代码中,通过setNavigationDelegate方法设置了一个NavigationDelegate对象,并实现了onNavigationRequest回调。

WebView触发导航请求时,onNavigationRequest回调会被调用,并传入一个NavigationRequest对象,其中包含了请求的URL等信息。

在回调中,你可以根据请求的URL进行判断,决定是否允许页面跳转。返回NavigationDecision.navigate表示允许跳转,返回NavigationDecision.prevent表示阻止跳转。

通过导航请求拦截,你可以实现一些自定义的导航控制逻辑,例如:

  • 限制只允许跳转到特定域名或路径的页面。

  • 在跳转到外部链接时,提示用户确认是否离开当前页面。

  • 对于某些URL,可以直接在Flutter中处理,而不是在WebView中加载。

  • 记录或统计页面跳转的情况,用于分析用户行为。

除了onNavigationRequest回调外,NavigationDelegate还提供了其他一些回调方法:

  • onPageStarted: 页面开始加载时触发。

  • onPageFinished: 页面加载完成时触发。

  • onProgress: 页面加载进度变化时触发。

  • onWebResourceError: 页面加载过程中发生错误时触发。

你可以根据需要实现这些回调,以便在页面加载的不同阶段执行相应的操作。

例如:

controller.setNavigationDelegate(NavigationDelegate(// 页面开始加载onPageStarted: (String url) {print('页面开始加载: $url');},// 页面加载完成onPageFinished: (String url) {print('页面加载完成: $url');},// 页面加载进度变化onProgress: (int progress) {print('页面加载进度: $progress%');},// 页面加载错误onWebResourceError: (WebResourceError error) {print('页面加载错误: ${error.description}');},
));

通过实现NavigationDelegate的回调方法,你可以更好地控制和响应WebView的页面导航事件,实现更加灵活和可定制的WebView集成方案。

以上就是WebView导航请求拦截的相关内容,通过设置NavigationDelegate并实现相应的回调方法,你可以对WebView的页面导航进行精细化的控制和处理。

3. JavaScript交互

WebView提供了与页面中JavaScript代码交互的能力,可以在Flutter和网页之间进行双向通信。通过设置JavaScript执行模式、调用JavaScript方法以及处理JavaScript消息等方式,可以实现Flutter和网页之间的数据传递和功能交互。

3.1 设置JavaScript执行模式

在使用WebViewJavaScript交互之前,需要先设置页面的JavaScript 执行模式。可以通过WebViewControllersetJavaScriptMode 方法来设置不同的执行模式。

// 启用JavaScript,不做任何限制
controller.setJavaScriptMode(JavaScriptMode.unrestricted);// 禁用JavaScript
controller.setJavaScriptMode(JavaScriptMode.disabled);

JavaScriptMode枚举提供了两种模式:

  • JavaScriptMode.unrestricted: 不对JavaScript执行做任何限制,允许执行任何JavaScript代码。

  • JavaScriptMode.disabled: 完全禁用JavaScript,不允许执行任何 JavaScript代码。

根据实际需求选择合适的JavaScript执行模式。如果需要与页面进行交互,就需要启用JavaScript;如果出于安全考虑,可以禁用 JavaScript

3.2 调用JavaScript方法

在启用JavaScript的情况下,可以通过WebViewControllerrunJavaScript方法在页面中执行JavaScript代码。

// 执行JavaScript代码
controller.runJavaScript('alert("Hello from Flutter!")');

runJavaScript方法接受一个字符串参数,表示要执行的JavaScript代码。可以在字符串中编写任意的JavaScript代码,例如调用页面中定义的函数、修改页面元素、获取页面数据等。

// 调用页面中的JavaScript函数
controller.runJavaScript('showMessage("Hello from Flutter!")');// 修改页面元素的内容
controller.runJavaScript('document.getElementById("message").innerText = "Modified by Flutter"');// 获取页面数据并传递给Flutter
controller.runJavaScript('window.flutter_inappwebview.callHandler("myHandler", document.title)');

通过runJavaScript方法,可以在Flutter中动态地执行 JavaScript代码,实现对网页的控制和交互。

3.3 处理JavaScript消息

除了主动调用JavaScript方法外,还可以通过注册JavaScript通道的方式,处理JavaScript通道的方式,处理网页发送的消息。可以使用WebViewControlleraddJavaScriptChannel方法注册一个JavaScript通道,用于接收来自网页的消息。

// 注册JavaScript通道
controller.addJavaScriptChannel('myChannel',onMessageReceived: (JavaScriptMessage message) {print('从JavaScript接收到消息: ${message.message}');// 处理接收到的消息},
);

addJavaScriptChannel方法接受两个参数:

  • nameJavaScript通道的名称,在网页中通过该名称向Flutter发送消息。

  • onMessageReceived:接收到消息时的回调函数,可以在其中处理接收到的消息。

在网页中,可以通过window.flutter_inappwebview.callHandler方法向指定的JavaScript通道发送消息。

addJavaScriptChannel方法接受两个参数:

  • nameJavaScript通道的名称,在网页中通过该名称向Flutter发送消息。

  • onMessageReceived:接收到消息时的回调函数,可以在其中处理接收到的消息。

在网页中,可以通过window.flutter_inappwebview.callHandler方法向指定的JavaScript通道发送消息。

// 在网页中向Flutter发送消息
window.flutter_inappwebview.callHandler('myChannel', 'Hello from JavaScript!');

当网页调用window.flutter_inappwebview.callHandler方法时,Flutter中注册的对应JavaScript通道的onMessageReceived回调函数将被触发,可以在回调函数中接收并处理消息。

通过JavaScript通道,可以实现网页向Flutter发送消息,Flutter接收并处理消息的功能,实现了网页到Flutter的单向通信。

需要注意的是,JavaScript通道的名称在Flutter和网页中要保持一致,才能正确地发送和接收消息。

通过设置JavaScript执行模式、调用JavaScript方法以及处理JavaScript消息,可以在Flutter和网页之间实现双向的数据传递和功能交互。根据实际需求,灵活运用这些方法,可以构建功能丰富、交互性强的WebView应用。

4. 页面加载事件

WebView在加载页面的过程中会触发一系列事件,通过设置WebViewControllernavigationDelegate属性,可以监听并处理这些事件。NavigationDelegate提供了多个回调方法,用于获取页面加载的不同阶段和状态。

4.1 开始加载

WebView开始加载一个新页面时,会触发onPageStarted回调。可以通过实现该回调方法来获取页面开始加载的事件。

controller.setNavigationDelegate(NavigationDelegate(onPageStarted: (String url) {print('页面开始加载: $url');// 执行其他操作,如显示加载指示器等},),
);

onPageStarted回调中,可以获取到当前开始加载的页面URL。可以根据需要执行一些操作,例如显示加载指示器、更新界面状态等。

例如:

controller.setNavigationDelegate(NavigationDelegate(onPageStarted: (String url) {setState(() {isLoading = true; // 设置加载状态为true});print('页面开始加载: $url');},),
);

在上面的示例中,当页面开始加载时,通过setState方法将isLoading状态设置为true,表示正在加载中。同时,将当前加载的URL打印出来。

4.2 加载进度

在页面加载过程中,WebView会不断触发onProgress回调,提供当前页面加载的进度信息。可以通过实现该回调方法来获取页面加载进度的变化事件。

controller.setNavigationDelegate(NavigationDelegate(onProgress: (int progress) {print('页面加载进度: $progress%');// 根据进度更新界面,如更新进度条等},),
);

onProgress回调接收一个整数参数progress,表示当前页面加载的进度,取值范围为0100。可以根据进度值更新界面,例如更新进度条的显示状态。

例如:

controller.setNavigationDelegate(NavigationDelegate(onProgress: (int progress) {setState(() {loadingProgress = progress; // 更新加载进度值});print('页面加进度值: $progress%');},),
);

在上面的示例中,通过setState方法将当前的加载进度值loadingProgress更新为最新的进度值。同时,将当前的加载进度打印出来。

可以在界面上使用进度条组件,如LinearProgressIndicator,根据loadingProgress的值来更新进度条的显示状态。

LinearProgressIndicator(value: loadingProgress / 100, // 将进度值转换为0到1之间的数值
),

通过监听WebViewonProgress回调,可以实时获取页面加载的进度,并根据需要更新界面,提供更好的用户体验。

4.3 加载完成

WebView完成页面加载时,会触发onPageFinished回调。可以通过实现该回调方法来获取页面加载完成的事件。

controller.setNavigationDelegate(NavigationDelegate(onPageFinished: (String url) {print('页面加载完成: $url');// 执行其他操作,如隐藏加载指示器等},),
);

onPageFinished回调中,可以获取到当前加载完成的页面URL。可以根据需要执行一些操作,例如隐藏加载指示器、更新界面状态等。
例如:

controller.setNavigationDelegate(NavigationDelegate(onPageFinished: (String url) {setState(() {isLoading = false; // 设置加载状态为false});print('页面加载完成: $url');},),
);

4.4 加载错误处理

WebView加载页面的过程中,可能会遇到一些错误,如网络连接失败、资源无法加载等。可以通过实现NavigationDelegateonWebResourceError回调来获取和处理这些错误事件。

controller.setNavigationDelegate(NavigationDelegate(onWebResourceError: (WebResourceError error) {print('页面加载错误: ${error.description}');// 处理错误,如显示错误提示、执行错误恢复逻辑等},),
);

onWebResourceError回调接收一个WebResourceError对象作为参数,该对象包含了错误的相关信息,如错误描述、错误代码等。可以根据这些信息进行错误处理,例如显示错误提示、执行错误恢复逻辑等。

例如:

controller.setNavigationDelegate(NavigationDelegate(onWebResourceError: (WebResourceError error) {setState(() {loadingError = error.description; // 保存错误描述});print('页面加载错误: ${error.description}');// 显示错误提示对话框showDialog(context: context,builder: (BuildContext context) {return AlertDialog(title: const Text('页面加载错误'),content: Text(error.description),actions: <Widget>[TextButton(onPressed: () {Navigator.of(context).pop();},child: const Text('确定'),),],);},);},),
);

在上面的示例中,当页面加载过程中发生错误时,通过setState方法将错误描述保存到loadingError变量中。同时,将错误描述打印出来。
接下来,使用showDialog方法显示一个错误提示对话框,将错误描述作为对话框的内容显示给用户。用户可以通过点击"确定"按钮关闭对话框。
通过监听 WebViewonWebResourceError回调,可以捕获页面加载过程中的错误事件,并根据需要进行相应的错误处理,如显示错误提示、执行错误恢复逻辑、记录错误日志等。这样可以提高应用的健壮性和用户体验。
需要注意的是,onWebResourceError回调可能会被多次触发,因为页面加载过程中可能会发生多个资源加载错误。可以根据实际需求决定是否对每个错误都进行处理,或者只处理某些特定类型的错误。
通过合理地处理 WebView 的加载完成和加载错误事件,可以让应用更加稳定和友好,提供更好的用户体验。

5. Cookie管理

WebView中的Cookie管理可以通过WebViewCookieManager类来实现。WebViewCookieManager提供了一些方法来设置、获取和清除Cookie数据。

5.1 设置Cookie

可以使用WebViewCookieManagersetCookie方法来设置Cookie数据。该方法接受一个Uri对象和一个表示Cookie数据的字符串作为参数。例如:

import 'package:webview_flutter/webview_flutter.dart';// 设置Cookie
await WebViewCookieManager().setCookie(const WebViewCookie(name: 'my_cookie',value: 'cookie_value',domain: 'example.com',path: '/',),
);

在上面的示例中,通过WebViewCookieManagersetCookie方法设置了一个名为"my_cookie"的Cookie,其值为"cookie_value",域为"example.com",路径为"/"

在上面的示例中,通过WebViewCookieManagersetCookie方法设置了一个名为"my_cookie"Cookie,其值为"cookie_value",域为"example.com",路径为"/"

5.2 获取Cookie

可以使用WebViewCookieManagergetCookies方法来获取当前的Cookie数据。该方法返回一个Future,其结果是一个包含所有Cookie的**Set<Cookie>**集合。例如:

import 'package:webview_flutter/webview_flutter.dart';// 获取Cookie
final Set<WebViewCookie> cookies = await WebViewCookieManager().getCookies(const Uri(scheme: 'https', host: 'example.com'),
);// 打印Cookie信息
for (final WebViewCookie cookie in cookies) {print('Cookie: ${cookie.name} = ${cookie.value}');
}

在上面的示例中,通过WebViewCookieManagergetCookies方法获取了指定Uri下的所有CookiegetCookies方法接受一个Uri对象作为参数,表示要获取Cookie的域名和路径。

获取到的Cookie集合可以进行遍历,打印出每个Cookie的名称和值。

5.3 清除Cookie

可以使用WebViewCookieManagerclearCookies方法来清除所有的Cookie数据。该方法会删除WebView中存储的所有Cookie。例如:

import 'package:webview_flutter/webview_flutter.dart';// 清除所有Cookie
await WebViewCookieManager().clearCookies();

在上面的示例中,通过调用WebViewCookieManagerclearCookies方法,可以清除WebView中存储的所有Cookie数据。

调用clearCookies方法后,之前设置的所有Cookie将被删除,WebView将不再携带这些Cookie信息进行请求。

需要注意的是,清除Cookie操作是全局的,会影响所有使用WebView的页面和请求。因此,请谨慎使用clearCookies方法,只在必要时进行清除操作。

通过合理地使用WebViewCookieManager提供的setCookiegetCookiesclearCookies方法,可以方便地管理WebView中的Cookie数据,实现对Cookie的设置、获取和清除操作,从而满足不同的业务需求。

6. 缓存管理

WebView提供了缓存管理的功能,可以通过WebViewController执行JavaScript代码的方式对缓存进行添加、查看和清除操作。下面我们来详细介绍这些缓存管理的用法。

6.1 添加缓存

可以通过WebViewControllerrunJavaScript方法执行JavaScript代码,将数据添加到缓存中。例如,使用localStorage对象将数据存储到本地缓存中:

// 添加缓存数据
controller.runJavaScript('''localStorage.setItem('key', 'value');
''');

在上面的示例中,通过runJavaScript方法执行了一段JavaScript代码。使用localStorage对象的setItem方法,将键值对'key': 'value'存储到本地缓存中。

localStorageWeb Storage API提供的一种本地存储机制,可以在浏览器中持久化存储键值对数据。通过localStorage.setItem方法可以将数据添加到缓存中,数据会一直保留,直到被显式删除或清除缓存。

6.2 查看缓存

同样,可以通过WebViewController的runJavaScriptReturningResult方法执行JavaScript代码,获取当前缓存中的数据。例如,使用localStorage对象获取缓存中的数据:

// 查看缓存数据
final String value = await controller.runJavaScriptReturningResult('''localStorage.getItem('key');
''');
print('缓存值: $value');

在上面的示例中,通过runJavaScriptReturningResult方法执行了一段JavaScript代码,并返回执行结果。使用localStorage对象的getItem方法,根据指定的键'key'获取对应的缓存值。

runJavaScriptReturningResult方法会返回一个Future,其结果是JavaScript代码的返回值。通过await关键字等待异步操作完成,可以获取到缓存中存储的值,并将其打印出来。

6.3 清除缓存

WebViewController提供了clearCache方法,用于清除WebView的缓存数据。调用该方法会删除WebView中的所有缓存,包括本地存储、会话存储、Cookie等。

// 清除缓存
await controller.clearCache();

在上面的示例中,通过调用WebViewControllerclearCache方法,可以清除WebView中的所有缓存数据。

调用clearCache方法后,之前通过JavaScript代码添加到缓存中的数据将被删除,WebView的缓存空间将被清空。这样可以释放存储空间,并确保后续的数据请求获取到最新的内容。

需要注意的是,clearCache方法是一个异步操作,需要使用await关键字等待其完成。在清除缓存的过程中,WebView可能会短暂地变得不可用,因此建议在合适的时机执行清除操作,例如在应用启动时或用户手动触发清除缓存的操作时。

7. 加载本地内容

WebView不仅可以加载网络上的页面,还支持加载本地的HTML文件、Flutter资源文件以及HTML字符串内容。下面我们来详细介绍这些加载本地内容的方法。

7.1 加载本地HTML文件

WebViewController提供了loadFile方法,可以加载本地文件系统中的HTML文件。该方法接受一个表示文件路径的字符串作为参数。

假设我们在Flutter项目的assets目录下有一个名为local.htmlHTML文件,可以通过以下代码加载该文件:

// 加载本地HTML文件
await controller.loadFile('assets/local.html');

在上面的示例中,通过WebViewController的loadFile方法加载了位于assets目录下的local.html文件。

loadFile方法会根据指定的文件路径查找并加载对应的HTML文件。文件路径可以是相对于Flutter项目根目录的相对路径,也可以是绝对路径。

需要注意的是,在使用loadFile方法加载本地HTML文件时,需要确保文件存在且路径正确。如果文件不存在或路径错误,WebView将无法正确加载文件内容。

7.2 加载Flutter资源

除了加载本地文件系统中的HTML文件,WebViewController还提供了loadFlutterAsset方法,用于加载Flutter应用中的资源文件。

假设我们在Flutter项目的assets目录下有一个名为flutter_asset.htmlHTML文件,可以通过以下代码加载该资源文件:

// 加载Flutter资源文件
await controller.loadFlutterAsset('assets/flutter_asset.html');

在上面的示例中,通过WebViewControllerloadFlutterAsset方法加载了位于assets目录下的flutter_asset.html文件。

loadFlutterAsset方法会在Flutter应用的资源文件中查找指定的文件,并将其加载到WebView中。文件路径应该是相对于Flutter项目的assets目录的相对路径。

使用loadFlutterAsset方法加载Flutter资源文件时,需要确保在pubspec.yaml文件中正确声明了要加载的资源文件。例如:

flutter:assets:- assets/flutter_asset.html

通过在pubspec.yaml文件中的flutter部分声明资源文件,可以确保在构建应用时将这些文件打包到应用的资源中,从而能够通过loadFlutterAsset方法进行加载。

7.3 加载HTML字符串

除了加载本地文件和Flutter资源外,WebViewController还提供了loadHtmlString方法,可以直接加载HTML字符串内容。

// 加载HTML字符串
await controller.loadHtmlString('''<html><body><h1>Hello, Flutter!</h1><p>This is an HTML string loaded in WebView.</p></body></html>
''');

在上面的示例中,通过WebViewControllerloadHtmlString方法加载了一段HTML字符串内容。

loadHtmlString方法接受一个表示HTML内容的字符串作为参数,并将其直接加载到WebView中进行显示。这种方式适用于动态生成的HTML内容或从其他来源获取的HTML字符串。

使用loadHtmlString方法加载HTML字符串时,可以在字符串中包含完整的HTML结构,包括<html><body>等标签。WebView会将该字符串作为完整的HTML页面进行解析和渲染。

需要注意的是,通过loadHtmlString方法加载的HTML内容是在内存中生成的,并没有对应的本地文件或网络资源。因此,如果HTML内容中引用了外部资源(如图片、样式表等),需要确保这些资源可以正确加载,否则可能会影响页面的显示效果。

通过合理地使用loadFileloadFlutterAssetloadHtmlString方法,可以灵活地加载本地的HTML文件、Flutter资源文件以及HTML字符串内容,满足不同的需求场景。这样可以在WebView中显示各种本地内容,提供更加丰富和定制化的用户体验。

相关文章:

Flutter笔记:关于WebView插件的用法(上)

Flutter笔记 关于WebView插件的用法&#xff08;上&#xff09; - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:htt…...

计算机毕业设计Python+Django农产品推荐系统 农产品爬虫 农产品商城 农产品大数据 农产品数据分析可视化 PySpark Hadoop Hive

课题研究的意义&#xff0c;国内外研究现状、水平和发展趋势 研究意义21世纪是一个信息爆炸的时代&#xff0c;人们在日常生活中可接触到的信息量非常之巨大。推荐系统逐步发展&#xff0c;其中又以个性化推荐系统最为瞩目。个性化推荐系统的核心在于个性化推荐算法&#xff0c…...

phpcms仿蚁乐购淘宝客网站模板

phpcms仿蚁乐购网站模板&#xff0c;淘宝客行业模板免费下载&#xff0c;该模板网站很容易吸引访客点击&#xff0c;提升ip流量和pv是非常有利的。本套模板采用现在非常流行的全屏自适应布局设计&#xff0c;且栏目列表以简洁&#xff0c;非常时尚大气。页面根据分辨率大小而自…...

leetcode695 岛屿的最大面积

题目 给你一个大小为 m x n 的二进制矩阵 grid 。 岛屿 是由一些相邻的 1 (代表土地) 构成的组合&#xff0c;这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0&#xff08;代表水&#xff09;包围着。 岛屿的面积是岛上值…...

小程序无法调用服务端问题排查

1、问题描述 突然有一天线上的小程序不能登录&#xff0c;经查小程序无法调用。经查无法小程序页面无法调用后台服务。 2、排查过程 由于无法登录小程序发布服务器&#xff0c;无法测试小程序前端服务器到服务端网络&#xff0c;并且小程序无法看到日志。所以就得从服务端和网…...

Linux:多线程的操作

多线程操作 进程与线程线程的创建 create_pthread创建线程池给线程传入对象的指针 线程等待 pthread_join退出线程 pthread_exit线程等待参数 retval 与 线程退出参数 retval 线程中断 pthread_cancel获取线程编号 pthread_self线程分离 pthread_detach 进程与线程 进程是资源…...

kunpeng的aarch64架构cpu、openeuler系统、昇腾服务器适配文档转换功能(doc转docx、ppt转pptx)

一、安装flatpak sudo yum install flatpak flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo二、安装libreoffice flatpak install flathub org.libreoffice.LibreOffice三、使用 对于使用 flatpak 安装的 LibreOffice,不需要手…...

unity 打包PC安装包中常见文件的功能

目录 前言 一、打包好的文件 二、常用文件 1.文件夹XXX_Data 2.文件夹MonoBleedingEdge 3.文件夹XXX_Data内部 三、文件的应用 1.如果你替换了一个图片 2.如果你新增了或减少了图片和资源 3.场景中有变动 4.resources代码加载的资源改了 5.如果你代码替换了 四、作…...

【Ardiuno】实验使用ESP32单片机实现高级web服务器暂时动态图表功能(图文)

接下来&#xff0c;我们继续实验示例代码中的Wifi“高级web服务器”&#xff0c;配置相关的无线密码后&#xff0c;开始实验 #include <WiFi.h> #include <WiFiClient.h> #include <WebServer.h> #include <ESPmDNS.h>const char *ssid "XIAOFE…...

深入浅出服务网格(Service Mesh):现代微服务架构的护航者

什么是服务网格&#xff1f; 服务网格是一种专用于处理微服务间通信的基础设施层&#xff0c;通常以轻量级代理&#xff08;sidecar&#xff09;的形式部署在每个服务实例旁边。它主要负责以下几项任务&#xff1a; 服务发现&#xff1a;自动检测和注册服务实例&#xff0c;使…...

node调试

vscode安装插件&#xff1a;JavaScript Debugger (Nightly) 点击后生成一个launch.json文件 打断点&#xff0c;并发送一个请求来执行代码到断点处 按右上的向下箭头&#xff0c;进入源码&#xff0c;进行查看&#xff0c;左边查看变量等值...

docker拉取镜像失败超时的解决方法,docker配置国内镜像源

更换国内源 创建或修改 /etc/docker/daemon.json 文件 安装docker后一般只有 /etc/docker 这个目录 下面并没有 daemon.json 文件 我们直接创建 &#xff1a; vim /etc/docker/daemon.json {"registry-mirrors" : ["https://registry.docker-cn.com"…...

建造气膜结构体育馆需要注意的事项—轻空间

气膜结构体育馆以其快速建造、低成本、灵活性高等优势&#xff0c;越来越受到各类运动场所的青睐。气膜结构利用空气压力支撑膜材&#xff0c;从而形成自持结构&#xff0c;无需传统的钢筋混凝土框架。这类建筑适用于各种气候条件&#xff0c;且可根据需要快速搭建和拆卸。然而…...

使用脚手架创建vue2项目(关闭eslint语法检查 、运行项目时自动打开网址、src文件夹简写方法)

使用脚手架创建vue2项目会默认安装的插件&#xff08;eslint) 这个插件是检查语法的。 假设我们在main.js中定义了一个变量&#xff0c;没有使用 eslint 就会检测出错误 &#xff08;事实是我们并没有写错而是eslint 给我们判断是错的&#xff0c;所以这样会很麻烦&#xff…...

谷粒商城实战(036 k8s集群学习2-集群的安装)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第343p-第p345的内容 k8s 集群安装 kubectl --》命令行操作 要进入服务器 而且对一些不懂代码的产品经理和运维人员不太友好 所以我们使用可视化…...

复旦微FMQL20SM全国产ARM+FPGA核心板,替代xilinx ZYNQ7020系列

FMQL20SM核心板一款全国产工业核心板。基于复旦微FMQL20S400M四核ARM Cortex-A7&#xff08;PS端&#xff09; FPGA可编程逻辑资源&#xff08;PL端&#xff09;异构多核SoC处理器设计的全国产工业核心板&#xff0c;PS端主频高达1GHz。 核心板简介 FMQL20SM核心板是一款全国…...

NPM常见问题

文章目录 NPM常见问题1. 使用淘宝源安装包出错2. listen EADDRINUSE 服务端口被占用报错3. npm start 启动后过一会崩溃结束&#xff1a;内存溢出4. npm install的时候使用特定的源安装5. npm安装指定版本、最新版本6. npm ERR! cb() never called! 解决7. Unable to authentic…...

二开版视频CMS完整运营源码/新版漂亮APP手机模板/集成员分销功能等

一个二开的影视CMS&#xff0c;直接上传源码至网站根目录&#xff0c;访问网站域名即可安装。 测试环境&#xff1a;Nginx 1.20.1—MySQL 5.6.50–PHP-7.2&#xff08;安装拓展/fileinfo&#xff09; 上传源码&#xff0c;访问域名直接安装 后台地址&#xff1a;域名/MDadmi…...

JavaScript的数组排序

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...

从Log4j和Fastjson RCE漏洞认识jndi注入

文章目录 前言JNDI注入基础介绍靶场搭建漏洞验证注入工具 log4j RCE漏洞分析漏洞靶场检测工具补丁绕过 Fastjson RCE漏洞分析漏洞靶场检测工具补丁绕过 总结 前言 接着前文的学习《Java反序列化漏洞与URLDNS利用链分析》&#xff0c;想了解为什么 Fastjson 反序列化漏洞的利用…...

7-25 数字三角形问题

7-25 数字三角形问题 分数 10 全屏浏览 作者 夏仁强 单位 贵州工程应用技术学院 给定一个由n行数字组成的数字三角形如下图所示。试设计一个算法&#xff0c;计算出从三角形的顶至底的一条路径&#xff0c;使该路径经过的数字总和最大。 对于给定的由n行数字组成的数字三角…...

【Kafka专栏 08】ZooKeeper的Watch机制:不就是个“小喇叭”吗?

作者名称&#xff1a;夏之以寒 作者简介&#xff1a;专注于Java和大数据领域&#xff0c;致力于探索技术的边界&#xff0c;分享前沿的实践和洞见 文章专栏&#xff1a;夏之以寒-kafka专栏 专栏介绍&#xff1a;本专栏旨在以浅显易懂的方式介绍Kafka的基本概念、核心组件和使用…...

三极管的厄利效应(early effect)

詹姆斯M厄利(James M. Early)发现的现象&#xff0c;厄利效应&#xff08;英语&#xff1a;Early effect&#xff09;&#xff0c;又译厄尔利效应&#xff0c;也称基区宽度调制效应&#xff0c;是指当双极性晶体管&#xff08;BJT&#xff09;的集电极&#xff0d;射极电压VCE改…...

Maven: 编码GBK的不可映射字符不能编译

使用mvn compile命令&#xff0c;出现错误: 编码GBK的不可映射字符不能编译。这是因为代码或注释中存在中文引起的&#xff0c;一般在ide中会自动处理编译时的字符集&#xff0c;就不会碰到这个错误。这个错误是在生成代码后&#xff0c;其中自动加上了中 文注释&#xff0c;手…...

《web应用技术》第十一次课后作业

1、验证过滤器进行权限验证的原理。 Filter过滤器&#xff1a;javaweb三大组件(Servlet,Filter,Listener)之一&#xff1b;过滤器可以把对资源的请求拦截下来&#xff0c;从而实现一些特殊功能&#xff1b;过滤器一般完成一些通用操作&#xff0c;比如登录校验等。 执行对应的…...

flutter中实现首行缩进两端对齐

刚开始进行搜索&#xff0c;发现很多都是让在每段开始的时候采用空格进行填充&#xff0c;但是采用这种形式之后&#xff0c;不知道为何首行直接溢出了&#xff0c;最后采用下面方法进行实现的。 RichText(text: TextSpan(children: [WidgetSpan(child: Container(width: 20, …...

Vitis HLS 学习笔记--Vitis Accelerated Libraries介绍

目录 1. 简介 2. 库的文件结构 3. 分类介绍 3.1 blas 3.2 codec 3.3 data_analytics 3.4 data_compression 3.5 data_mover 3.6 database 3.7 dsp 3.8 graph 3.9 hpc 3.10 motor_control 3.11 quantitative_finance 3.12 security 3.13 solver 3.14 utils 3…...

Vue3-滑动到最右验证功能

1、思路 1、在登录页面需要启动向右滑块验证 2、效果图 3、文章地址&#xff1a;滑动验证码的实现-vue-simple-verify 2、成分分析 1、由三块构成&#xff0c;分别是底部条、拖动条、拖动移动部分 2、底部条&#xff1a;整体容器&#xff0c;包括背景、边框和文字&#xf…...

深入理解MyBatis XML配置文件

MyBatis是一款优秀的持久层框架&#xff0c;简化了数据库操作的复杂性&#xff0c;提高了开发效率。在MyBatis中&#xff0c;XML配置文件扮演了重要角色&#xff0c;用于配置数据源、事务管理、SQL映射等内容。本文将详细介绍MyBatis的XML配置文件&#xff0c;帮助读者更好地理…...

006 CentOS 7.9 elasticsearch7.10.0安装及配置

文章目录 一、安装Elasticsearch 7.10.0二、安装Logstash 7.10.0三、配置防火墙和网络访问可能出现的错误配置 Elasticsearch官方网址&#xff1a; https://www.elastic.co Elasticsearch中文官网地址&#xff1a;https://www.elastic.co/cn/products/elasticsearch https://…...

临沂网站制作公司/宁波seo关键词排名优化

Redis下一小节&#xff1a;1-11 特性七&#xff1a;复制 Redis特性六&#xff1a;简单 1、Redis单机核心代码数少 带着问题去看Redis源代码会简单很多 2、Redis不依赖外部库 Memcache就依赖与外部库&#xff1a;libevent 3、Redis是单线程模型 单线程意味着无论是客户端还…...

phpmyadmin做网站/百度竞价推广费用

C语言程序设计实训之四价格竞猜游戏设计,周跃进徐州建筑职业技术学院电子信息工程系,在《购物街》游戏中&#xff0c;能否通过编程模拟整个过程&#xff0c;该如何做&#xff1f;,看一段录相&#xff0c;思考一个问题,《购物街》游戏节目是通过佳宾猜商品价格&#xff0c;本实训…...

上海网站论坛建设/湖南网站网络推广哪家奿

一、为什么跳槽&#xff1f; 我做后端五年多了&#xff0c;同很多人一样&#xff0c;我大学的专业和程序员这个行业没有任何的关系。毕业后&#xff0c;很迷茫&#xff0c;就做了门槛相对来说较低的服务行业&#xff0c;之后&#xff0c;就一个偶然的机会接触了程序员这个行业…...

想给公司做个网站 怎么做/网页设计首页

考虑一个字节是如何从设备发往运程服务器以及如何从远程服务器将这个字节接收到设备&#xff0c;这个过程只需要几百毫秒时间&#xff0c;不过确要求网络设备都能正常工作才行。设备网络和网络互联的复杂性导致了分层网络的产生。分层网络将这种复杂环境划分成了更加易于管理的…...

网站建设+开源/如何申请一个网站域名

作者&#xff1a;jerryWu转发连接&#xff1a;https://juejin.im/post/5ec48f84e51d45788266753apdf.js实战&#xff0c;含水印、电子签章解决方案项目涉及到移动端查看电子合同的问题&#xff0c;前前后后试了三种方案&#xff0c;真是一步一个坑&#xff0c;三种方案各有各的…...

手机软件制作和做网站相同/搜狗官方网站

核心步骤 阿里云准备 centos_8_0&#xff0c;安全组设置&#xff08;可以虚拟机代替&#xff09;linux下jdk maven git 配置添加SSH公钥从gitee克隆源代码liunx下docker安装git拉取项目代码执行项目中sql的数据库脚本修改项目配置并启动 新建目录 #tmp存放临时安装包 mkdir …...