如何在Flutter ListView中显示数据库中的Base64 WebP图片
Flutter中显示Base64格式WebP图片到ListView的解决方案
核心思路
将数据库存储的Base64字符串解码为Uint8List,再通过Flutter的Image.memory组件渲染WebP图片。需要先处理可能存在的Base64前缀(如data:image/webp;base64,),避免解码失败。
修改后的_buildRow组件代码
同步解码版本(适合小体积图片)
import 'dart:convert'; import 'package:flutter/material.dart'; Widget _buildRow(Product product) { // 移除Base64前缀(如果存在) String base64Content = product.mainPhoto; final webpPrefix = 'data:image/webp;base64,'; if (base64Content.startsWith(webpPrefix)) { base64Content = base64Content.substring(webpPrefix.length); } // 解码为字节数组 final imageBytes = base64Decode(base64Content); return ListTile( leading: Image.memory( imageBytes, width: 60, height: 60, fit: BoxFit.cover, // 解码失败时显示占位图标 errorBuilder: (context, error, stackTrace) => const Icon(Icons.broken_image), ), title: Text(product.name), // 替换为产品实际的标题字段 subtitle: Text(product.description ?? ''), // 可选:添加产品描述 ); }
异步解码版本(适合大体积图片,避免UI卡顿)
如果图片体积较大,同步解码可能导致ListView滑动卡顿,用FutureBuilder异步处理:
import 'dart:convert'; import 'package:flutter/material.dart'; Widget _buildRow(Product product) { return ListTile( leading: FutureBuilder<Uint8List>( future: _decodeWebPImage(product.mainPhoto), builder: (context, snapshot) { if (snapshot.hasData) { return Image.memory( snapshot.data!, width: 60, height: 60, fit: BoxFit.cover, ); } else if (snapshot.hasError) { return const Icon(Icons.broken_image); } // 加载中显示进度指示器 return const SizedBox( width: 60, height: 60, child: Center(child: CircularProgressIndicator(strokeWidth: 2)), ); }, ), title: Text(product.name), ); } // 抽离解码逻辑为异步方法 Future<Uint8List> _decodeWebPImage(String base64String) async { final webpPrefix = 'data:image/webp;base64,'; if (base64String.startsWith(webpPrefix)) { base64String = base64String.substring(webpPrefix.length); } return base64Decode(base64String); }
注意事项
- 确保数据库中存储的Base64字符串是有效的WebP格式,否则会触发
errorBuilder显示占位图标。 - 配合
ListView.builder的懒加载特性,避免一次性解码所有图片导致内存占用过高。 - 可通过
Image.memory的cacheWidth/cacheHeight参数指定缓存尺寸,进一步优化性能。
内容的提问来源于stack exchange,提问作者Oleksandr Lysak
相关产品推荐
相关产品推荐

