You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

  1. 在首页初始化并保存InAppWebViewController实例
  2. 跳转其他页面时传递该控制器实例
  3. 其他页面通过控制器直接修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 05:54:24