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

Flutter中页面加载时如何预加载网络图片?(MVC架构URL过期场景)

Flutter MVC架构下预加载临时有效期图片方案

核心思路

把服务器返回的临时URL对应的图片资源提前下载并缓存为内存中的Uint8List,页面重建时直接使用内存中的二进制数据渲染图片,彻底避免重复请求过期URL的问题。

具体实现步骤

1. 模型层(Model)处理数据与图片预加载

在数据模型中新增存储图片二进制数据的字段,同时封装预加载方法:

class ItemModel {
  final String tempImageUrl;
  Uint8List? imageBytes; // 存储预加载后的图片二进制数据

  ItemModel({required this.tempImageUrl});

  // 预加载图片的异步方法
  Future<void> preloadImage() async {
    try {
      final response = await http.get(Uri.parse(tempImageUrl));
      if (response.statusCode == 200) {
        imageBytes = response.bodyBytes;
      }
    } catch (e) {
      // 处理加载失败场景,比如打印日志或标记错误状态
      print('图片预加载失败: $e');
    }
  }
}

2. 控制器层(Controller)统筹数据加载与预加载

在控制器中,请求服务器数据完成后,批量触发所有图片的预加载:

class ItemController {
  List<ItemModel> itemList = [];

  // 从服务器拉取数据并批量预加载图片
  Future<void> loadDataAndPreload() async {
    // 替换为实际的服务器请求逻辑
    final rawData = await _fetchFromServer();
    itemList = rawData.map((item) => ItemModel(tempImageUrl: item['imageUrl'])).toList();

    // 并行预加载所有图片,提升效率
    await Future.wait(itemList.map((model) => model.preloadImage()));
  }

  Future<List<Map<String, dynamic>>> _fetchFromServer() async {
    // 模拟服务器请求延迟
    await Future.delayed(const Duration(seconds: 1));
    return [
      {'imageUrl': 'https://example.com/temp-img-1.jpg'},
      {'imageUrl': 'https://example.com/temp-img-2.jpg'},
    ];
  }
}

3. 视图层(View)使用预加载的图片数据

页面渲染时直接读取模型中存储的二进制数据,不再依赖临时URL:

class ItemPage extends StatefulWidget {
  const ItemPage({super.key});

  @override
  State<ItemPage> createState() => _ItemPageState();
}

class _ItemPageState extends State<ItemPage> {
  final ItemController _controller = ItemController();
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    _initPageData();
  }

  Future<void> _initPageData() async {
    await _controller.loadDataAndPreload();
    setState(() {
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) {
      return const Center(child: CircularProgressIndicator());
    }

    return ListView.builder(
      itemCount: _controller.itemList.length,
      itemBuilder: (context, index) {
        final item = _controller.itemList[index];
        return item.imageBytes != null
            ? Image.memory(item.imageBytes!)
            : const SizedBox(height: 100, child: Placeholder()); // 加载失败显示占位图
      },
    );
  }
}

额外优化建议

  • 图片数量较多时,可分批次预加载,避免一次性占用过多网络资源
  • 预加载过程中可添加全局进度提示,提升用户感知
  • 为imageBytes添加非空断言的安全处理,防止渲染时出现空指针异常

内容的提问来源于stack exchange,提问作者Florent Tornicelli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 16:02:13