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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 01:53:28