我是 Flutter 新手,目前遇到图像加载问题。在我的应用程序中,我正在从 Firebase 数据服务器查询提要帖子,其中包含图像的 URL。 向下滚动时,新帖子正在加载,而当前旧帖子似乎正在被破坏,向上滚动时需要再次下载。 有没有快速的解决方案来缓存图像以减少带宽流量?
提前致谢!
这是我的代码:
class Feed extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<List<Post>>(
stream: FeedService().getPosts(), application layer
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text('No posts available'));
}
final posts = snapshot.data!;
return ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
return PostItem(post: posts[index]);
},
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CreatePostScreen()),
);
},
child: Icon(Icons.add),
heroTag: 'createPostButton'
),
);
}
}
class PostItem extends StatefulWidget {
final Post post;
PostItem({required this.post});
@override
State<PostItem> createState() => _PostItemState();
}
class _PostItemState extends State<PostItem> {
bool _isBookmarked = false;
bool _isLiked = false;
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(widget.post.userProfileImageUrl),
),
title: Text(widget.post.username),
subtitle: Text(widget.post.timestamp.toDate().toString()),
trailing: Icon(Icons.more_vert),
),
CachedNetworkImage(
imageUrl: widget.post.imageUrl,
fit: BoxFit.cover,
width: double.infinity,
cacheManager: CacheManager(
Config(
'customCacheKey',
stalePeriod: Duration(days: 7),
maxNrOfCacheObjects: 100,
),
),
placeholder: (context, url) => Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => Icon(Icons.error),
),
// Like and comment section
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
IconButton(
onPressed: () {
setState(() {
_isLiked = !_isLiked;
});
},
icon: Icon(_isLiked ? Icons.thumb_up : Icons.thumb_up_outlined),
),
const SizedBox(width: 10),
IconButton(
onPressed: () {},
icon: const Icon(Icons.comment_outlined),
),
],
),
IconButton(
onPressed: () {
setState(() {
_isBookmarked = !_isBookmarked;
});
},
icon: Icon(_isBookmarked ? Icons.bookmark : Icons.bookmark_outline),
)
],
),
),
// Post caption or text (if needed)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Text(
widget.post.description,
style: TextStyle(fontSize: 16),
),
),
const SizedBox(height: 10),
],
),
);
}
}
要在 Flutter 应用程序中有效缓存图像并减少从 URL 加载图像时的带宽使用量,您可以使用 CachedNetworkImage 包。通过这样做,图像将被缓存在本地,并且当用户滚动浏览提要时不需要重新下载。
实现方法如下: 设置全局缓存管理器:这可确保所有图像共享相同的缓存设置,并从跨应用程序的缓存中受益。 将 CachedNetworkImage 与全局缓存管理器一起使用:这将自动处理图像加载和缓存。 第 1 步:创建全局缓存管理器 您可以创建一个单独的类来管理缓存设置:
类 MyCacheManager { 静态最终 CacheManager 实例 = CacheManager( 配置( '自定义缓存键', stalePeriod: Duration(days: 7), // 缓存图像7天 maxNrOfCacheObjects: 200, // 缓存中最多 200 个图像 ), ); }
第 2 步:将 CachedNetworkImage 与全局缓存管理器一起使用 更新您的小部件以使用 CachedNetworkImage 小部件中的全局缓存管理器:
类 PostItem 扩展 StatelessWidget { 最后的帖子;
PostItem({必填this.post});
@覆盖 小部件构建(BuildContext上下文){ 退卡( 边距:const EdgeInsets.all(10), 子项:列( crossAxisAlignment:CrossAxisAlignment.start, 孩子们: [ 列表图块( 领先:圆形头像( 背景图像:网络图像(post.userProfileImageUrl), ), 标题:文本(帖子.用户名), 副标题:Text(post.timestamp.toDate().toString()), 尾随:图标(Icons.more_vert), ), 缓存网络图像( 图片网址:post.imageUrl, 适合:BoxFit.cover, 宽度:双无穷大, cacheManager: MyCacheManager.instance, // 使用全局缓存管理器 占位符:(上下文,url)=>中心(子:CircularProgressIndicator()), errorWidget: (上下文, url, 错误) => 图标(Icons.error), ), ], ), ); } }
使用此设置,图像将在本地缓存,从而减少滚动时重新下载图像的需要。全局缓存管理器确保缓存设置一致并集中管理。根据您的应用程序的需求调整缓存设置,例如 stalePeriod 和 maxNrOfCacheObjects。