https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter
webview_flutter_4.10.0_docs.txt
webview_flutter_4.10.0_docs.txt
webview_flutter_4.10.0_docs.txt
==================================================
==================================================
WebView 核心控制器,负责加载内容、配置参数及交互
// 构造函数
WebViewController.fromPlatformCreationParams(
PlatformWebViewControllerCreationParams params
)
// 主要方法
1. loadRequest(Uri uri, {
Map<String, String>? headers,
Uint8List? body,
LoadRequestMethod method = LoadRequestMethod.get
}) // 加载URL请求:cite[8]
2. setJavaScriptMode(JavaScriptMode mode) // 设置JS执行模式
3. addJavaScriptChannel(String name, {
required void Function(JavaScriptMessage) onMessageReceived
}) // 注册JS通信通道:cite[4]
4. runJavaScript(String code) // 执行JS代码
5. runJavaScriptReturningResult(String code) // 执行JS并返回结果
6. setUserAgent(String? userAgent) // 设置User-Agent
7. clearCache() // 清理缓存(不包含本地存储):cite[6]
// 平台扩展方法
if (controller.platform is AndroidWebViewController) {
(controller.platform as AndroidWebViewController)
.setMediaPlaybackRequiresUserGesture(false); // Android特有配置:cite[6]
}
// 构造函数
WebViewWidget({
required WebViewController controller,
Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers
})
// 手势配置示例
gestureRecognizers: {
Factory<VerticalDragGestureRecognizer>(() => VerticalDragGestureRecognizer())
}
导航事件处理委托
NavigationDelegate({
NavigationRequestCallback? onNavigationRequest,
PageEventCallback? onPageStarted,
PageEventCallback? onPageFinished,
ProgressCallback? onProgress,
WebResourceErrorCallback? onWebResourceError
})
// 拦截示例
onNavigationRequest: (request) {
if (request.url.contains('blocked.com')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
}:cite[4]:cite[10]
final cookieManager = WebViewCookieManager();
await cookieManager.setCookie(
WebViewCookie(
name: 'session',
value: '123',
domain: 'example.com',
path: '/',
httpOnly: true
)
)
==================================================
==================================================
enum JavaScriptMode {
disabled, // 禁用JS执行
unrestricted // 允许JS完全执行:cite[10]
}
enum CacheMode {
loadDefault, // 默认缓存策略
loadNoCache, // 跳过缓存
loadElseNetwork, // 优先使用缓存
loadCacheElseNetwork
}
enum PlaybackMediaTypes {
all, // 所有媒体类型
audio, // 音频
video // 视频
}:cite[6]
class WebResourceError {
final int errorCode;
final String description;
final bool isForMainFrame; // 是否主框架错误7
}
==================================================
==================================================
// 初始化参数
AndroidWebViewControllerCreationParams(
displayWithHybridComposition: true, // 强制混合渲染模式
enableDebugging: true // 启用调试模式
)
// 启用Material组件
if (Platform.isAndroid) {
WebView.platform = SurfaceAndroidWebView();
}:cite[3]:cite[6]
WebKitWebViewControllerCreationParams(
allowsInlineMediaPlayback: true, // 内联媒体播放
mediaTypesRequiringUserAction: {PlaybackMediaTypes.video}
)
==================================================
==================================================
// 执行简单JS
controller.runJavaScript('alert("Hello")');
// 获取JS返回值
final height = await controller.runJavaScriptReturningResult(
'document.body.scrollHeight'
) as int;:cite[8]
// 注册通道
controller.addJavaScriptChannel('Bridge', (message) {
print('收到JS消息: ${message.message}');
});
// JS调用方式
window.Bridge.postMessage('Hello from JS');
// 注入ResizeObserver监听
controller.runJavaScript('''
new ResizeObserver(entries =>
Report.postMessage(document.body.scrollHeight)
).observe(document.body)
''');
// Dart端接收
controller.addJavaScriptChannel('Report', (message) {
setState(() => height = double.parse(message.message));
}):cite[4]
==================================================
controller.loadRequest(
Uri.parse('https://api.example.com'),
method: LoadRequestMethod.post,
body: Uint8List.fromList(utf8.encode('data')),
headers: {'Content-Type': 'application/json'}
)
// 加载Assets文件
controller.loadFlutterAsset('assets/page.html');
// 加载字符串
controller.loadHtmlString('Local Content
',
baseUrl: 'https://base.example.com'):cite[8]
// 获取滚动位置
final position = await controller.getScrollPosition();
// 滚动到指定位置
controller.scrollTo(0, 500);
==================================================
==================================================
WebView 类已废弃,拆分为:
WebViewController
:控制逻辑WebViewWidget
:渲染组件:cite[6]方法变更:
evaluateJavascript
→ runJavaScriptReturningResult
loadUrl
→ loadRequest
clearCache
不再清理本地存储:cite[6]导航委托迁移:
// 旧版
WebView(navigationDelegate: ...)
// 新版
controller.setNavigationDelegate(...):cite[6]
==================================================
启用Android调试:
dart AndroidWebViewController.enableDebugging(true);:cite[6]
性能监控:
dart controller.enablePerformanceMetrics( metrics: {PerformanceMetric.resourceTiming} ):cite[6]
缓存策略:
dart controller.setCacheMode( cacheMode: CacheMode.loadElseNetwork, maxCacheSize: 100 * 1024 * 1024 // 100MB ):cite[6]
注:实际开发需根据目标平台导入对应实现包:
dependencies:
webview_flutter: ^4.10.0
webview_flutter_android: ^4.3.0 # Android 扩展
webview_flutter_wkwebview: ^3.17.0 # iOS/macOS 扩展:cite[6]
D:\F\lvjun\lib\inserted_web_seven\tell_to_ai\my_summary\webview_flutter_4.10.0_guide.txt
webview_flutter_4.10.0_guide.txt
webview_flutter_4.10.0_guide.txt
一、核心作用
webview_flutter 是 Flutter 官方提供的跨平台 WebView 组件,用于在移动应用中嵌入网页内容。其核心功能包括:
多平台支持:基于 Android WebView / iOS WKWebView 实现
双向通信:支持 JavaScript 与 Flutter 的交互
导航控制:拦截处理页面跳转请求
媒体支持:内联视频播放、自动媒体加载策略
安全策略:Cookie 管理、HTTPS 证书校验
场景类型 | 具体案例 | 技术实现要点 |
---|---|---|
内嵌浏览器 | 应用内置网页浏览器 | 导航控制 、手势支持 |
动态内容展示 | 商品详情页/新闻页 | 远程URL加载 、缓存优化 |
混合开发 | Flutter+Web 混合应用 | JS通信 、本地HTML加载 |
第三方集成 | 支付/地图/客服系统 | 安全域限制 、POST请求 |
企业应用 | OA 系统/数据看板 | Cookie认证 、HTTPS强制 |
二、典型应用场景
场景类型 具体案例 技术实现要点
内嵌浏览器 应用内置网页浏览器 导航控制、手势支持
动态内容展示 商品详情页/新闻页 远程 URL 加载、缓存优化
混合开发 Flutter+Web 混合应用 JS 通信、本地 HTML 加载
第三方服务集成 支付/地图/客服系统 安全域限制、POST 请求
企业应用 OA 系统/数据看板 Cookie 认证、HTTPS 强制
参数 | 作用/说明 | 注意事项 |
---|---|---|
javascriptMode |
启用/禁用 JS 执行 | 需设置 unrestricted 启用复杂交互 |
userAgent |
自定义浏览器标识 | 需适配目标网站 UA 检测规则 |
gestureRecognizers |
自定义手势识别 | 需处理与 Flutter 手势的冲突 |
参数 | 作用/说明 | 注意事项 |
---|---|---|
onNavigationRequest |
拦截处理页面跳转请求 | 需返回 NavigationDecision 枚举值 |
onPageFinished |
页面加载完成事件监听 | 适合注入 JS 脚本或统计加载耗时 |
参数 | 作用/说明 | 注意事项 |
---|---|---|
cacheMode |
定义资源缓存策略 | 推荐 loadElseNetwork 平衡性能 |
preloadPages |
预加载指定 URL 页面 | 需控制数量避免内存过高 |
enablePerformanceMetrics |
启用性能指标采集 | 需选择关键指标避免性能开销 |
三、关键配置参数
1. 基础配置
参数 类型 默认值 作用
javascriptMode JavaScriptMode disabled 启用/禁用 JS 执行
userAgent String? 系统默认 自定义浏览器标识
gestureRecognizers Set<Factory> null 自定义手势识别
2. 导航控制
参数 类型 说明
onNavigationRequest NavigationDecision Function(NavigationRequest) 导航拦截回调
onPageFinished void Function(String) 页面加载完成回调
3. 性能优化
参数 类型 说明
cacheMode CacheMode 缓存策略(loadElseNetwork 等)
preloadPages List<String> 预加载 URL 列表
enablePerformanceMetrics Set<PerformanceMetric> 性能指标采集
AndroidWebViewControllerCreationParams(
displayWithHybridComposition: true, // 必须启用
enableDebugging: kDebugMode, // 调试模式
)
iOS 特有:
WebKitWebViewControllerCreationParams(
allowsInlineMediaPlayback: true,
mediaTypesRequiringUserAction: {PlaybackMediaTypes.video}
)
四、标准使用流程
final controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setUserAgent('MyApp/1.0')
..setNavigationDelegate(NavigationDelegate(
onNavigationRequest: (request) => _handleNavigation(request)
));
// 加载远程URL
controller.loadRequest(Uri.parse('https://example.com'));
// 加载本地HTML
controller.loadHtmlString('''
Local Content
''', baseUrl: 'https://base.example.com');
// 注册JS通道
controller.addJavaScriptChannel('Scanner', (message) {
final result = scanBarcode();
controller.runJavaScript('onScanResult("$result")');
});
// 处理支付回调
controller.setNavigationDelegate(NavigationDelegate(
onNavigationRequest: (request) {
if (request.url.startsWith('alipay://')) {
_handlePayment(request.url);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
}
));
// 设置缓存策略
controller.setCacheMode(
cacheMode: CacheMode.loadElseNetwork,
maxCacheSize: 200 * 1024 * 1024, // 200MB
);
// 启用性能监控
controller.enablePerformanceMetrics(
metrics: {PerformanceMetric.resourceTiming}
);
五、注意事项
1.混合渲染模式
Android 必须启用混合渲染以避免白屏:
WebViewWidget(
creationParams: AndroidWebViewCreationParams(
displayWithHybridComposition: true
)
)
2.内存管理
在页面销毁时需手动释放资源:
void dispose() {
controller.dispose();
super.dispose();
}
3.平台差异处理
iOS 文件上传:需实现 WKFileUploadPanelDelegate
Android 证书校验:通过 WebViewClient.onReceivedSslError 处理
4.调试工具
// 启用远程调试
if (kDebugMode) {
WebViewController.setWebContentsDebuggingEnabled(true);
}
此总结涵盖了该包的核心使用要点,实际开发时建议参考 官方文档 获取最新 API 变更信息。对于复杂场景(如 WebRTC 支持),需结合平台原生代码扩展实现。
==================================================
==================================================
// 在 StatefulWidget 中初始化
late final WebViewController controller;
void initState() {
super.initState();
controller = WebViewController();
}
注意:
==================================================
==================================================
controller
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setUserAgent('MyApp/1.0')
..setBackgroundColor(Colors.transparent)
..setNavigationDelegate(NavigationDelegate(
onNavigationRequest: _handleNavigation
));
关键配置说明:
==================================================
==================================================
// Flutter端注册通道
controller.addJavaScriptChannel(
'Scanner',
onMessageReceived: (JavaScriptMessage message) {
final result = scanBarcode();
controller.runJavaScript('onScanResult("$result")');
}
);
// JS调用示例(网页中):
// window.Scanner.postMessage('start');
通道规范:
==================================================
==================================================
NavigationDelegate _buildDelegate() {
return NavigationDelegate(
onNavigationRequest: (request) {
if (request.url.contains('ads')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
onPageFinished: (url) {
controller.runJavaScript('initPage()');
}
);
}
拦截策略:
==================================================
==================================================
// 加载远程URL(带自定义Header)
controller.loadRequest(
Uri.parse('https://api.example.com'),
headers: {'Authorization': 'Bearer xxx'},
method: LoadRequestMethod.post
);
// 加载本地HTML
controller.loadHtmlString('''
Local Content
''');
加载方式对比:
方法 | 适用场景 | 注意事项 |
---|---|---|
loadRequest | 常规网页加载 | 支持GET/POST |
loadHtmlString | 动态内容生成 | 必须设置baseUrl |
loadFlutterAsset | 打包的本地HTML文件 | 需在pubspec.yaml声明 |
==================================================
==================================================
// 手势冲突处理
WebViewWidget(
controller: controller,
gestureRecognizers: {
Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer()
)
}
)
// 处理支付回调
controller.setNavigationDelegate(NavigationDelegate(
onUrlChange: (url) {
if (url?.scheme == 'alipay') {
_handlePayment(url!);
}
}
));
典型交互场景:
==================================================
==================================================
// 设置缓存策略
controller.setCacheMode(
cacheMode: CacheMode.loadElseNetwork,
maxCacheSize: 200 * 1024 * 1024, // 200MB
);
// 预加载关键资源
controller.loadRequest(Uri.parse('https://example.com/static/main.css'));
// 监控性能指标
final metrics = await controller.getPerformanceMetrics();
print('DOM加载耗时: ${metrics['domContentLoaded']}ms');
优化策略:
==================================================
==================================================
void dispose() {
controller.clearCache(); // 可选清理缓存
controller.dispose(); // 必须释放控制器
super.dispose();
}
释放场景:
==================================================
==================================================
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewPage extends StatefulWidget {
const WebViewPage({super.key});
State<WebViewPage> createState() => _WebViewPageState();
}
class _WebViewPageState extends State<WebViewPage> {
late final WebViewController controller;
void initState() {
super.initState();
controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel('Bridge', onMessageReceived: _handleMessage)
..setNavigationDelegate(_buildDelegate())
..loadRequest(Uri.parse('https://example.com'));
}
NavigationDelegate _buildDelegate() {
return NavigationDelegate(
onNavigationRequest: (request) {
return request.url.contains('ads')
? NavigationDecision.prevent
: NavigationDecision.navigate;
}
);
}
void _handleMessage(JavaScriptMessage message) {
print('Received: ${message.message}');
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('WebView Demo')),
body: WebViewWidget(controller: controller),
);
}
void dispose() {
controller.dispose();
super.dispose();
}
}