Flutter全局复用WebView组件:仅加载一次并动态修改URL参数
实现WebView实例复用:切换页面仅修改URL不重新加载
需求概述
创建加载根URL(如www.example.com)的自定义WebView组件,要求App启动时仅加载一次WebView,切换至其他页面时仅修改URL参数,无需重新加载WebView实例。
现有方案问题分析
当前代码中每次调用_loadPages()都会创建新的InAppWebView实例,通过Navigator传递的是全新Widget而非已加载的WebView实例,无法实现复用;同时onWebViewCreated中重复调用loadUrl属于冗余操作,initialUrlRequest已完成初始加载。
解决方案
核心思路是复用InAppWebViewController实例,而非传递WebView Widget:
- 在首页初始化并保存
InAppWebViewController实例 - 跳转其他页面时传递该控制器实例
- 其他页面通过控制器直接修改URL,无需重新创建WebView
完整代码示例
首页(WebView初始化页面)
import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { InAppWebViewController? _webViewController; final GlobalKey webViewKey = GlobalKey(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('首页'), actions: [ TextButton( onPressed: () => Navigator.push( context, MaterialPageRoute( builder: (context) => AnotherScreen(controller: _webViewController), ), ), child: const Text('跳转至其他页面'), ), ], ), body: InAppWebView( key: webViewKey, initialUrlRequest: URLRequest(url: Uri.parse('https://www.example.com')), initialOptions: InAppWebViewGroupOptions( crossPlatform: InAppWebViewOptions( clearCache: true, cacheEnabled: true, javaScriptEnabled: true, useShouldOverrideUrlLoading: true, supportZoom: false, userAgent: defaultTargetPlatform == TargetPlatform.iOS ? "iPhone" : "Android", ), android: AndroidInAppWebViewOptions( useHybridComposition: true, clearSessionCache: true, offscreenPreRaster: true, ), ), onWebViewCreated: (controller) => _webViewController = controller, onLoadStart: (_, url) => print('开始加载: $url'), onConsoleMessage: (_, msg) => print('控制台消息: ${msg.message}'), ), ); } }
其他页面(修改URL页面)
class AnotherScreen extends StatelessWidget { final InAppWebViewController? controller; const AnotherScreen({Key? key, required this.controller}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('其他页面'), actions: [ TextButton( onPressed: () { // 方式1:加载带参数的新URL(适用于非单页应用) controller?.loadUrl( urlRequest: URLRequest(url: Uri.parse('https://www.example.com?param=123')), ); // 方式2:通过JS修改URL(适用于单页应用,无页面重载) // controller?.evaluateJavascript( // source: "window.history.pushState({}, '', '?param=123');", // ); }, child: const Text('修改URL参数'), ), ], ), body: const Center( child: Text('点击上方按钮修改首页WebView的URL'), ), ); } }
关键说明
- 复用控制器:通过传递
InAppWebViewController实例,确保所有页面操作的是同一个WebView实例,避免重复初始化 - URL修改方式:
- 非单页应用使用
loadUrl加载新URL,WebView会更新内容但实例不变 - 单页应用推荐使用JS修改URL(
window.history.pushState),完全避免页面重载,提升体验
- 非单页应用使用
- 避免传递Widget:直接传递WebView Widget会导致每次创建新实例,无法达到复用目的
内容的提问来源于stack exchange,提问作者Milan Surelia
相关产品推荐
相关产品推荐

