Flutter中AnimatedList内Image.network无网时崩溃问题求助
Flutter无网滚动AnimatedList时图片组件崩溃问题解决
问题描述
在Flutter应用的AnimatedList列表项中,使用Image.network展示图片:
Image.network( url, errorBuilder: (context, error, stacktrace) => Container(color: Colors.red), width: 80, height: 80, cacheWidth: 80, cacheHeight: 80, )
无网络连接时向下滚动列表,即使配置了errorBuilder,应用仍偶尔崩溃,错误信息:
The following SocketException was thrown resolving an image codec:
Failed host lookup: 'i.discogs.com' (OS Error: No address associated with hostname, errno = 7)
改用cached_network_image包后问题依旧:
CachedNetworkImage( placeholder: (context, url) => Container(color: Colors.red), errorWidget: (context, url, error) => Container(color: Colors.red), imageUrl: url, memCacheWidth: 80, memCacheHeight: 80, )
错误信息:
The following _ClientSocketException was thrown resolving an image codec:
Failed host lookup: 'i.discogs.com'
补充信息
- 已创建可复现问题的示例项目
- 已在Flutter官方仓库提交Bug
- 已向cached_network_image包仓库提交Bug
解决方案
1. 提前检查网络状态
在加载图片前判断当前网络连接状态,无网时直接返回错误占位组件,避免发起无效网络请求:
import 'package:connectivity_plus/connectivity_plus.dart'; // 封装图片组件 Widget buildNetworkImage(String url) { return FutureBuilder<ConnectivityResult>( future: Connectivity().checkConnectivity(), initialData: ConnectivityResult.none, builder: (context, snapshot) { if (snapshot.data != ConnectivityResult.none) { return Image.network( url, errorBuilder: (context, error, stacktrace) => Container(color: Colors.red), width: 80, height: 80, cacheWidth: 80, cacheHeight: 80, ); } else { return Container(color: Colors.red, width: 80, height: 80); } }, ); }
2. 自定义异常捕获的ImageProvider
包装NetworkImage,在内部捕获SocketException,避免异常向上抛出导致崩溃:
import 'dart:typed_data'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; class SafeNetworkImage extends NetworkImage { SafeNetworkImage(String url) : super(url); @override Future<ImageInfo> loadImage(ImageConfiguration configuration) async { try { return await super.loadImage(configuration); } on SocketException { return ImageInfo(image: await decodeImageFromList(Uint8List(0))); } } } // 使用方式 Image( image: SafeNetworkImage(url), errorBuilder: (context, error, stacktrace) => Container(color: Colors.red), width: 80, height: 80, )
3. 使用FutureBuilder包裹图片加载逻辑
将图片加载逻辑封装为Future,通过FutureBuilder捕获所有异步异常:
import 'dart:typed_data'; import 'package:flutter/widgets.dart'; Future<ImageProvider> _loadImage(String url) async { try { return NetworkImage(url); } catch (_) { return MemoryImage(Uint8List(0)); } } // 在列表项中使用 FutureBuilder<ImageProvider>( future: _loadImage(url), builder: (context, snapshot) { if (snapshot.hasData) { return Image( image: snapshot.data!, errorBuilder: (context, error, stacktrace) => Container(color: Colors.red), width: 80, height: 80, ); } else { return Container(color: Colors.red, width: 80, height: 80); } }, )
4. 临时规避方案(等待官方修复)
如果上述方案仍有问题,可临时在无网状态下直接使用本地占位图,完全跳过网络请求:
Widget buildImage(String url) { // 替换为实际网络状态判断逻辑 bool hasNetwork = false; if (hasNetwork) { return CachedNetworkImage( placeholder: (context, url) => Container(color: Colors.red), errorWidget: (context, url, error) => Container(color: Colors.red), imageUrl: url, memCacheWidth: 80, memCacheHeight: 80, ); } else { return Container(color: Colors.red, width: 80, height: 80); } }
内容的提问来源于stack exchange,提问作者matteoh
相关产品推荐
相关产品推荐

