Flutter如何实现WebView加载前带网络检测及Snackbar提示的启动页
Flutter 集成WebView应用启动页前置网络检测实现方案
1. 引入所需依赖
在项目根目录的pubspec.yaml中添加功能所需依赖:
dependencies: flutter: sdk: flutter webview_flutter: ^4.4.2 # 官方维护的WebView组件 connectivity_plus: ^5.0.2 # 跨平台网络状态检测组件
保存后执行flutter pub get完成依赖安装。
2. 配置平台必要权限
- Android端:在
android/app/src/main/AndroidManifest.xml的<manifest>标签下添加权限声明:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- iOS端:在
ios/Runner/Info.plist中添加网络访问配置:
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
3. 编写启动页逻辑
将启动页设为应用初始路由,页面初始化时自动触发网络检测:无网络则弹出常驻SnackBar提示用户重试,检测到可用网络后自动跳转至WebView页面。
import 'package:flutter/material.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'webview_page.dart'; class SplashPage extends StatefulWidget { const SplashPage({super.key}); @override State<SplashPage> createState() => _SplashPageState(); } class _SplashPageState extends State<SplashPage> { final Connectivity _connectivity = Connectivity(); @override void initState() { super.initState(); // 首帧渲染完成后触发网络检测 WidgetsBinding.instance.addPostFrameCallback((_) { _checkNetworkAndNavigate(); }); } Future<void> _checkNetworkAndNavigate() async { // 获取当前网络连接状态 final connectivityResult = await _connectivity.checkConnectivity(); // 判定为无网络时弹出提示 if (connectivityResult.contains(ConnectivityResult.none)) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: const Text('当前无可用网络,请检查网络设置后重试'), duration: const Duration(days: 365), // 常驻不自动消失 action: SnackBarAction( label: '重试', onPressed: () { ScaffoldMessenger.of(context).hideCurrentSnackBar(); _checkNetworkAndNavigate(); }, ), ), ); } return; } // 可选:延迟1秒展示启动页品牌元素,可根据需求调整时长或删除 await Future.delayed(const Duration(seconds: 1)); if (mounted) { // 替换路由进入WebView页面,禁止返回启动页 Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (context) => const WebViewPage()), ); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Center( // 替换为自身业务的启动页Logo、slogan等元素 child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const FlutterLogo(size: 120), const SizedBox(height: 24), const Text('应用加载中', style: TextStyle(fontSize: 16, color: Colors.grey)), ], ), ), ); } }
4. 编写WebView页面
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class WebViewPage extends StatefulWidget { const WebViewPage({super.key}); @override State<WebViewPage> createState() => _WebViewPageState(); } class _WebViewPageState extends State<WebViewPage> { late final WebViewController _webController; bool _pageLoading = true; @override void initState() { super.initState(); _webController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) // 按需开启JS权限 ..setNavigationDelegate( NavigationDelegate( onPageStarted: (url) { setState(() => _pageLoading = true); }, onPageFinished: (url) { setState(() => _pageLoading = false); }, ), ) ..loadRequest(Uri.parse('替换为实际需要加载的Web页面地址')); } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ WebViewWidget(controller: _webController), if (_pageLoading) const Center( child: CircularProgressIndicator(), ), ], ), ); } }
实现注意事项
- 基础网络检测的局限性:
connectivity_plus仅能判断设备是否连接到WiFi/蜂窝网络,无法验证是否能正常访问外网。如果需要更严谨的判断,可以在检测到网络连接后,发起一次轻量的HTTP请求验证连通性,确认正常后再跳转。 - Context安全校验:所有涉及页面跳转、SnackBar弹出的操作,必须先判断
mounted属性为true再执行,避免异步检测过程中页面销毁导致的上下文异常。 - SnackBar展示逻辑:无网络时SnackBar设置为常驻状态,避免提示自动消失导致用户无感知,用户点击重试按钮后再触发新一轮网络检测。
内容的提问来源于stack exchange,提问作者mary
相关产品推荐
相关产品推荐

