Flutter 中的图像缓存

问题描述 投票:0回答:1

我是 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 dart google-cloud-firestore
1个回答
0
投票

要在 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。

© www.soinside.com 2019 - 2024. All rights reserved.