Flutter数据缓存插件cached的使用

发布于 1周前 作者 nodeper 来自 Flutter

Flutter数据缓存插件cached的使用

简介

cached 是一个用于简化Dart类中缓存机制创建的简单包。它支持多种缓存策略,如LRU(Least Recently Used)算法,并且可以与持久化存储结合使用。本文将详细介绍如何在Flutter项目中使用cached插件进行数据缓存。

安装配置

添加依赖

首先,在pubspec.yaml文件中添加以下依赖:

dependencies:
  cached_annotation:

dev_dependencies:
  cached:
  build_runner:

或者直接运行命令来安装:

flutter pub add --dev cached
flutter pub add --dev build_runner
flutter pub add cached_annotation

运行生成器

为了使代码生成器生效,需要执行以下命令:

flutter pub run build_runner build

确保你的文件顶部包含必要的导入语句和部分声明:

import 'package:cached_annotation/cached_annotation.dart';

part 'some_file.cached.dart';

基本用法

使用@WithCache注解

为类添加缓存功能,可以通过@WithCache()注解实现。例如:

@WithCache(useStaticCache: true) // 可选参数:是否使用静态缓存
abstract mixin class RemoteRepository implements Repository, _$RemoteRepository {
  factory RemoteRepository({required SomeApiDataSource dataSource}) = _RemoteRepository;

  @Cached(
    ttl: 60,          // 缓存存活时间(秒)
    syncWrite: true,  // 同步写入模式
    limit: 100        // 最大缓存条目数
  )
  Future<SomeResponseType> getSthData() async {
    return await dataSource.getData();
  }
}

清除特定方法的缓存

你可以通过@ClearCached@ClearAllCached注解清除缓存。比如清除单个方法的缓存:

@ClearCached('getSthData')
void clearGetUserData();

或者清除所有缓存:

@clearAllCached
void clearAllData();

持久化存储

如果你希望将缓存保存到持久化存储中(如SharedPreferences),可以使用@PersistentCached注解。这要求你实现一个继承自CachedStorage接口的具体类,并将其实例分配给PersistentStorageHolder.storage

例如:

class MyStorageImpl extends CachedStorage {
  final _storage = MyExternalStorage();

  @override
  Future<Map<String, dynamic>> read(String key) async {
    return await _storage.read(key);
  }

  @override
  Future<void> write(String key, Map<String, dynamic> data) async {
    await _storage.write(key, data);
  }

  @override
  Future<void> delete(String key) async {
    await _storage.delete(key);
  }

  @override
  Future<void> deleteAll() async {
    await _storage.deleteAll();
  }
}

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  PersistentStorageHolder.storage = await MyStorageImpl();
  runApp(const MyApp());
}

示例代码

下面是一个完整的示例程序,展示了如何在Flutter应用中集成cached插件并实现简单的API响应缓存。

import 'package:flutter/material.dart';
import 'package:cached_annotation/cached_annotation.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

part 'main.cached.dart';

// 模拟的数据源
class ApiDataSource {
  static const String url = "https://jsonplaceholder.typicode.com/posts/1";

  Future<Map<String, dynamic>> getData() async {
    final response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
      return json.decode(response.body);
    } else {
      throw Exception('Failed to load post');
    }
  }
}

// 使用WithCache标记的仓库类
@WithCache()
abstract mixin class PostRepository implements _$PostRepository {
  factory PostRepository({required ApiDataSource dataSource}) = _PostRepository;

  final ApiDataSource _dataSource;

  @Cached(
    ttl: 60,
    syncWrite: true,
    where: shouldCacheResponse,
  )
  Future<Map<String, dynamic>> getPostData() async {
    return await _dataSource.getData();
  }

  bool shouldCacheResponse(Map<String, dynamic> response) {
    // 根据条件决定是否缓存
    return response['id'] != null && response['title'] != null;
  }

  @ClearCached('getPostData')
  void clearPostDataCache() {}
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: PostScreen(),
    );
  }
}

class PostScreen extends StatefulWidget {
  @override
  _PostScreenState createState() => _PostScreenState();
}

class _PostScreenState extends State<PostScreen> {
  final PostRepository repository = PostRepository(dataSource: ApiDataSource());
  Map<String, dynamic>? postData;

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

  Future<void> _fetchData() async {
    try {
      final data = await repository.getPostData();
      setState(() {
        postData = data;
      });
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Cached Plugin Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () => _fetchData(),
              child: Text('Fetch Data'),
            ),
            SizedBox(height: 20),
            postData != null
                ? Text('Title: ${postData!['title']}')
                : Text('No data available.'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                repository.clearPostDataCache();
                setState(() {
                  postData = null;
                });
              },
              child: Text('Clear Cache'),
            ),
          ],
        ),
      ),
    );
  }
}

此示例展示了如何利用cached插件快速设置一个带有缓存功能的API请求处理逻辑。通过点击按钮触发数据获取操作,并且可以手动清除缓存以重新加载最新数据。


更多关于Flutter数据缓存插件cached的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据缓存插件cached的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用cached_network_image插件进行数据缓存的示例代码。这个插件允许你从网络加载图片,并自动缓存它们,以便在后续的应用启动或页面刷新时能够快速加载。

首先,你需要在你的pubspec.yaml文件中添加cached_network_image依赖:

dependencies:
  flutter:
    sdk: flutter
  cached_network_image: ^3.1.0  # 请检查最新版本号

然后,运行flutter pub get来安装依赖。

接下来,你可以在你的Flutter应用中使用CachedNetworkImage小部件来加载和缓存网络图片。以下是一个简单的示例:

import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Cached Network Image Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Cached Network Image Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // 使用CachedNetworkImage加载并缓存网络图片
            CachedNetworkImage(
              imageUrl: 'https://example.com/path/to/your/image.jpg',
              placeholder: (context, url) => CircularProgressIndicator(),
              errorWidget: (context, url, error) => Icon(Icons.error),
              fit: BoxFit.cover,
              width: 300,
              height: 200,
            ),
            SizedBox(height: 20),
            // 另一个示例,展示不同配置
            CachedNetworkImage(
              imageUrl: 'https://example.com/another/image.png',
              placeholder: (context, url) => Icon(Icons.image),
              errorWidget: (context, url, error) => Text('Failed to load image'),
              retryCount: 3,  // 重试次数
              retryDuration: Duration(seconds: 2),  // 每次重试之间的间隔
              fadeDuration: Duration(milliseconds: 300),  // 图片加载完成时的淡入效果时长
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们展示了如何使用CachedNetworkImage小部件加载并缓存网络图片。你可以自定义placeholder(占位符,在图片加载时显示),errorWidget(当加载图片失败时显示的组件),以及其他一些配置选项,如retryCount(重试次数),retryDuration(每次重试之间的间隔),和fadeDuration(图片加载完成时的淡入效果时长)。

这样,你的应用就可以有效地缓存网络图片,提高用户体验。

回到顶部