Flutter数据缓存插件cached_repository的使用

Flutter数据缓存插件cached_repository的使用

pub package Last Commits Pull Requests Code size License

简单易用且可扩展的数据缓存库,可用于存储你需要的所有数据。 灵感来源于Android中的NetworkBoundResource

如果你觉得有用,请给项目点赞以支持我们

资源

开始使用

只需创建一个包含CachedRepository字段的类,并开始缓存数据:

class SomeClassRepository {
  SomeClassRepository(SomeClassApi someClassApi)
      : _cachedRepo = CachedRepository.persistent(
    'my_objects',
    fetch: (String key, [__]) => someClassApi.getObjects(key),
    decode: (json) => SomeClass.listFromJson(json),
    cacheDuration: const Duration(hours: 12),
  );

  final CachedRepository<String, List<SomeClass>> _cachedRepo;

  final _logger = Logger();

  Stream<Resource<List<SomeClass>>> getMyObjectsStream(
      String parameter, {
        bool forceReload = false,
      }) {
    _logger.d('SomeClassRepository => getMyObjectsStream');
    return _cachedRepo.stream(parameter, forceReload: forceReload);
  }

  Future<Resource<List<SomeClass>>> getMyObjects(
      String parameter, {
        bool forceReload = false,
      }) {
    _logger.d('SomeClassRepository => getMyObjects');
    return _cachedRepo.first(parameter, forceReload: forceReload);
  }

  Future<void> invalidate(String parameter) {
    _logger.d('SomeClassRepository => invalidate');
    return _cachedRepo.invalidate(parameter);
  }

  Future<void> removeObjectFromCache(
      String parameter, {
        /*required*/ String objectId,
      }) async {
    _logger.d('SomeClassRepository => removeObjectFromCache');
    return _cachedRepo.updateValue(parameter, (list) {
      return list.where((it) => it.id != objectId).toList(growable: false);
    });
  }

  Future<void> removeObjectsFromCache(
      String parameter, {
        /*required*/ List<String> objectIds,
      }) async {
    _logger.d('SomeClassRepository => removeObjectsFromCache');
    return _cachedRepo.updateValue(parameter, (list) {
      return list
          ?.where((it) => !objectIds.contains(it.id))
          ?.toList(growable: false);
    });
  }

  Future<void> clear(String parameter) {
    _logger.d('SomeClassRepository => clear');
    return _cachedRepo.clear(parameter);
  }
}

class SomeClass {
  final String id;

  SomeClass(this.id);

  factory SomeClass.fromJson(Map<String, dynamic> json) {
    return SomeClass(
      json['id'],
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
    };
  }

  static List<SomeClass> listFromJson(List<dynamic>/*?*/ jsonList) =>
      (jsonList ?? [])
          .map((json) => SomeClass.fromJson(json))
          .toList(growable: false);
}

abstract class SomeClassApi {
  factory SomeClassApi() => _SomeClassFakeApi();

  Future<List<SomeClass>> getObjects(String parameter);

  Future<void> create(String id);
}

class _SomeClassFakeApi implements SomeClassApi {
  final _logger = Logger();

  List<SomeClass> myObjects = [
    SomeClass('1'),
    SomeClass('2'),
    SomeClass('3'),
  ];

  [@override](/user/override)
  Future<List<SomeClass>> getObjects(String parameter) async {
    _logger.d('SomeClassFakeApi => getObjects');

    await Future.delayed(const Duration(seconds: 1));
    return myObjects;
  }

  [@override](/user/override)
  Future<void> create(String id) async {
    _logger.d('SomeClassFakeApi => create');

    await Future.delayed(const Duration(seconds: 1));
    myObjects = myObjects
      ..add(SomeClass(id))
      ..toList();
  }
}

你可以使用自己的类替换SomeClassSomeClassApi

欢迎提交拉取请求。

完整示例代码

import 'package:example/some_class_repository.dart';
import 'package:example/some_class_service.dart';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const _someParameter = 'key';

  final _logger = Logger();

  /*late final*/
  SomeClassService _service;

  [@override](/user/override)
  void initState() {
    final api = SomeClassApi();
    final repository = SomeClassRepository(api);
    _service = SomeClassService(
      someClassApi: api,
      someClassRepository: repository,
    );
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('标题'),
      ),
      body: Center(
        child: StreamBuilder(
          stream:
              _service.getMyObjectsStream(_someParameter, forceReload: true),
          builder: (context, res) {
            if (res.data?.hasData ?? false) {
              _logger.d(
                  'Value (stream): ${(res.data.data as List<SomeClass>).map((e) => e.toJson()).toList()}');
              return Text(
                  '数据: ${res.data.data.map((e) => e.toJson()).toList()}');
            } else if (res.data?.isError ?? false) {
              _logger.d('错误 (stream): ${res.data.error}');
            }
            _logger.d('加载中 (stream)');
            return const Text('正在加载...');
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _service.create(_someParameter),
        tooltip: '创建',
        child: const Icon(Icons.add),
      ),
    );
  }
}

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

1 回复

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


当然,cached_repository 是一个在 Flutter 中用于数据缓存的非常有用的库。它结合了数据获取和缓存机制,使得管理数据变得更加高效。以下是一个如何使用 cached_repository 的示例代码案例。

首先,确保你已经在 pubspec.yaml 文件中添加了 cached_repository 依赖:

dependencies:
  flutter:
    sdk: flutter
  cached_repository: ^x.y.z  # 请替换为最新版本号

然后运行 flutter pub get 来获取依赖。

接下来,我们来看一个具体的示例,假设我们要缓存从网络获取的用户数据。

1. 创建一个数据源类

import 'package:dio/dio.dart';
import 'package:cached_repository/cached_repository.dart';

class UserDataSource implements DataSource<UserModel, String> {
  final Dio dio;

  UserDataSource({required this.dio});

  @override
  Future<UserModel> fetchData(String key) async {
    // 模拟从网络获取用户数据
    final response = await dio.get('https://api.example.com/users/$key');
    return UserModel.fromJson(response.data);
  }
}

2. 创建用户模型类

class UserModel {
  final String id;
  final String name;
  final String email;

  UserModel({required this.id, required this.name, required this.email});

  factory UserModel.fromJson(Map<String, dynamic> json) {
    return UserModel(
      id: json['id'] as String,
      name: json['name'] as String,
      email: json['email'] as String,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
    };
  }
}

3. 创建缓存仓库类

import 'package:cached_repository/cached_repository.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'user_data_source.dart';
import 'user_model.dart';

class UserRepository extends CachedRepository<UserModel, String> {
  UserRepository({required UserDataSource dataSource})
      : super(
          dataSource: dataSource,
          cacheManager: DefaultCacheManager(),
          keyMapper: (UserModel data) => data.id, // 使用用户ID作为缓存键
        );
}

4. 使用缓存仓库

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'user_repository.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late UserRepository userRepository;
  UserModel? user;

  @override
  void initState() {
    super.initState();
    final dio = Dio();
    final userDataSource = UserDataSource(dio: dio);
    userRepository = UserRepository(dataSource: userDataSource);

    // 假设我们要获取ID为'1'的用户数据
    _fetchUserData('1');
  }

  Future<void> _fetchUserData(String userId) async {
    try {
      // 尝试从缓存中获取数据,如果缓存中没有,则从数据源获取并缓存
      user = await userRepository.fetch(userId);
      setState(() {});
    } catch (e) {
      print('Error fetching user data: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('User Data'),
        ),
        body: Center(
          child: user == null
              ? CircularProgressIndicator()
              : Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text('ID: ${user!.id}'),
                    Text('Name: ${user!.name}'),
                    Text('Email: ${user!.email}'),
                  ],
                ),
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个 UserDataSource 来从网络获取用户数据,一个 UserModel 来表示用户数据,一个 UserRepository 来结合数据源和缓存管理,最后在 MyApp 中使用 UserRepository 来获取并显示用户数据。

这个示例展示了如何使用 cached_repository 进行数据缓存,从而减少不必要的网络请求,提高应用性能。

回到顶部