Flutter WebView无法加载后端返回URL问题求助
Flutter WebView无法加载后端返回的自定义URL,但浏览器可正常打开
我在Flutter应用里用WebView加载后端返回的支付授权URL,WebView始终加载失败,但把这个URL复制到网页浏览器里却能正常打开。以下是相关代码和配置:
WebView实现代码
class MainPaymentScreen extends StatefulWidget { const MainPaymentScreen({super.key}); @override State<MainPaymentScreen> createState() => _MainPaymentScreenState(); } class _MainPaymentScreenState extends State<MainPaymentScreen> { String? _url; late WebViewController _webViewController; late AuthorizationUrl provider; bool _hasError = false; @override void initState() { super.initState(); _webViewController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setBackgroundColor(Color(0x00000000)) ..setNavigationDelegate( NavigationDelegate( onWebResourceError: (error) { setState(() { _hasError = true; }); Center(child: Text('An error occurred'),); }, onPageFinished: (url) { setState(() { _hasError = false; }); }, onNavigationRequest: (request) { if (request.url.startsWith('http://www.youtube.com')) { return NavigationDecision.prevent; } return NavigationDecision.navigate; }, ), ); } @override void didChangeDependencies() { super.didChangeDependencies(); // Access the provider and update the URL provider = Provider.of<AuthorizationUrl>(context); final newUrl = provider.authorization_url; // Load the URL only if it has changed if (_url != newUrl && newUrl.isNotEmpty) { _url = newUrl; print(newUrl); _webViewController.loadRequest(Uri.parse(_url!)); } } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: _url == null ? Center(child: CircularProgressIndicator()) : _hasError ? Center(child: Text('An error occurred')) : WebViewWidget(controller: _webViewController), ), ); } }
获取并存储后端URL的代码
class PaymentService { static Future<void> sendPayment( BuildContext context, { required String amount, required String email, required String currency, }) async { http.Response? response; try { final paymentEndpoint = 'http://10.0.2.2:3000/api/v1/receive-payment'; response = await http.post(Uri.parse(paymentEndpoint), headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ${EnvironConfig.secretKey}', }, body: jsonEncode({ "amount": amount, "email": email, "currency": currency, })); if (response.statusCode == 200) { final responseData = jsonDecode(response.body); final authUrl = responseData['authorization_url']; final reference = responseData['reference']; if (authUrl != null && reference != null) { Provider.of<AuthorizationUrl>(context, listen: false).authUrl(authUrl); // Provider.of<AuthorizationUrl>(context, listen: false).setReference(reference); // verifyPayment(reference: reference); print("Authorization URL: $authUrl"); print("Reference: $reference"); } else { print("Authorization URL or Reference is null."); } } else { print("Failed to send payment. Status code: ${response.statusCode}"); print("Response body: ${response.body}"); } } catch (e) { print("Exception occurred: $e"); } } }
AndroidManifest配置
<uses-permission android:name="android.permission.INTERNET"/> android:usesCleartextTraffic="true"
排查与解决建议
打印具体错误信息
在onWebResourceError里添加错误日志,比如:onWebResourceError: (error) { setState(() { _hasError = true; }); print('WebView加载错误: ${error.description}, 错误码: ${error.errorCode}'); },根据错误码能快速定位问题,比如证书错误、连接超时、URL解析失败等。
确保URL格式正确
后端返回的URL可能存在未编码的特殊字符,改用Uri.encodeFull解析:_webViewController.loadRequest(Uri.parse(Uri.encodeFull(_url!)));同时检查打印出的URL和浏览器打开的是否完全一致,避免有空格、转义字符等差异。
修正AndroidManifest配置
android:usesCleartextTraffic="true"必须放在<application>标签内,正确配置如下:<application android:label="你的应用名" android:icon="@mipmap/ic_launcher" android:usesCleartextTraffic="true"> <uses-permission android:name="android.permission.INTERNET"/> <!-- 其他配置 --> </application>调整状态监听逻辑
改用Consumer监听AuthorizationUrl的状态变化,避免didChangeDependencies触发不及时:@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Consumer<AuthorizationUrl>( builder: (context, authProvider, child) { final newUrl = authProvider.authorization_url; if (_url != newUrl && newUrl.isNotEmpty) { _url = newUrl; _webViewController.loadRequest(Uri.parse(Uri.encodeFull(_url!))); } return _url == null ? Center(child: CircularProgressIndicator()) : _hasError ? Center(child: Text('加载出错')) : WebViewWidget(controller: _webViewController); }, ), ), ); }临时关闭导航拦截测试
注释掉onNavigationRequest里的拦截逻辑,确认不是URL被误拦截导致无法加载。
内容的提问来源于stack exchange,提问作者Achievers Tv
相关产品推荐
相关产品推荐

