Flutter资源缓存插件cached_resource的使用
Flutter资源缓存插件cached_resource的使用
概述
cached_resource
是一个基于 NetworkBoundResource
方法实现的缓存插件,遵循单一数据源原则。它允许你定义一个缓存资源,在多个地方订阅更新,并确保只有一个网络请求会被调用,所有监听者都会接收到新的值。
使用步骤
1. 添加依赖
在你的 pubspec.yaml
文件中添加 cached_resource
作为依赖:
dependencies:
cached_resource: ^latest_version
2. 资源存储配置
默认情况下,该插件只提供了内存存储(In-Memory Storage)。如果需要持久化存储或安全存储,你需要添加额外的依赖包:
- 持久化存储:resource_storage_hive
- 安全存储:resource_storage_secure
3. 配置插件
在应用启动前,调用 ResourceConfig.setup
来配置存储工厂和日志记录器:
void main() {
// Configuration for cached_resource.
ResourceConfig.setup(
persistentStorageFactory: const HiveResourceStorageProvider(),
secureStorageFactory: const FlutterSecureResourceStorageProvider(),
logger: CustomLogger(), // 可选
);
runApp(const MyApp());
}
定义资源/仓库
根据使用的存储类型,你可以以多种方式创建资源。
内存缓存示例
class AccountBalanceRepository extends CachedResource<String, AccountBalance> {
AccountBalanceRepository(AccountBalanceApi api)
: super.inMemory(
'account_balance',
fetch: api.getAccountBalance,
cacheDuration: const CacheDuration(minutes: 15),
);
}
持久化缓存示例
class CategoryRepository {
CategoryRepository(CategoryApi api)
: _categoryResource = CachedResource.persistent(
'categories',
fetch: (_) => api.getCategories(),
cacheDuration: const CacheDuration(days: 15),
decode: Category.listFromJson,
);
final CachedResource<String, List<Category>> _categoryResource;
final _key = 'key';
Stream<Resource<List<Category>>> watchCategories() =>
_categoryResource.asStream(_key);
Future<void> removeCategoryFromCache(String categoryId) {
return _categoryResource.updateCachedValue(
_key,
(categories) => categories?.where((category) => category.id != categoryId).toList(),
);
}
Future<void> invalidate() => _categoryResource.invalidate(_key);
}
安全缓存示例
class ProductSecretCodeRepository extends CachedResource<String, String> {
ProductSecretCodeRepository(ProductApi api)
: super.secure(
'secret_code',
fetch: api.getProductSecretCode,
cacheDuration: const CacheDuration.newerStale(),
);
}
自定义资源存储
你可以通过扩展 ResourceStorage
来创建自定义存储:
class UserRepository extends CachedResource<String, User> {
UserRepository(UserApi api)
: super(
'users',
fetch: api.getUserById,
cacheDuration: const CacheDuration(days: 15),
storage: YourCustomStorage(),
);
}
监听资源流或获取值
获取单个值
void foo() async {
final resource = await resource.get(productId);
if (resource.hasData) {
final product = resource.data!;
// 处理产品数据
} else if (resource.isError) {
final error = resource.error;
final Product? productFromCache = resource.data;
// 显示错误或使用缓存数据
}
}
监听资源更新
void startListening() async {
_subscription = _categoryRepository.watchCategories().listen((resource) {
if (resource.hasData) {
final categories = resource.data!;
// 显示类别
} else if (resource.isError) {
final error = resource.error!;
final cachedCategories = resource.data;
// 处理错误
} else /*if (resource.isLoading)*/ {
// 显示加载状态
}
});
}
示例 Demo
以下是一个完整的示例应用,展示了如何使用 cached_resource
插件来管理产品列表及其详细信息页面:
import 'package:flutter/material.dart';
import 'package:cached_resource/cached_resource.dart';
import 'package:resource_storage_hive/resource_storage_hive.dart';
import 'package:resource_storage_secure/resource_storage_secure.dart';
void main() {
ResourceConfig.setup(
persistentStorageFactory: const HiveResourceStorageProvider(),
secureStorageFactory: const FlutterSecureResourceStorageProvider(),
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Cached Resource Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ProductListPage(),
);
}
}
class ProductListPage extends StatefulWidget {
@override
_ProductListPageState createState() => _ProductListPageState();
}
class _ProductListPageState extends State<ProductListPage> {
late final ProductRepository _repository;
@override
void initState() {
super.initState();
_repository = ProductRepository(ProductApi());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Products'),
),
body: StreamBuilder<Resource<List<Product>>>(
stream: _repository.watchProducts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final resource = snapshot.data!;
if (resource.hasData) {
return ListView.builder(
itemCount: resource.data!.length,
itemBuilder: (context, index) {
final product = resource.data![index];
return ListTile(
title: Text(product.title),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ProductDetailsPage(product: product),
),
);
},
);
},
);
} else if (resource.isError) {
return Center(child: Text('Error loading products'));
} else {
return Center(child: CircularProgressIndicator());
}
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
}
}
class ProductDetailsPage extends StatelessWidget {
final Product product;
ProductDetailsPage({required this.product});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(product.title),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(product.description),
),
);
}
}
这个示例展示了如何使用 cached_resource
插件来管理和显示产品列表,并在点击时导航到产品的详细信息页面。希望这些内容能帮助你更好地理解和使用 cached_resource
插件。
更多关于Flutter资源缓存插件cached_resource的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter资源缓存插件cached_resource的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用cached_resource
插件来进行资源缓存的示例代码。cached_resource
插件允许你缓存网络资源,例如图片、JSON数据等,以提高应用的性能和用户体验。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加cached_resource
的依赖:
dependencies:
flutter:
sdk: flutter
cached_resource: ^x.y.z # 请将x.y.z替换为最新版本号
然后运行flutter pub get
来获取依赖。
2. 初始化插件
在你的应用入口文件(通常是main.dart
)中,初始化CachedResource
插件:
import 'package:flutter/material.dart';
import 'package:cached_resource/cached_resource.dart';
void main() {
// 初始化CachedResource
CachedResource.init(
baseCacheDir: (await getApplicationDocumentsDirectory()).path,
logger: (message) {
// 你可以在这里实现日志记录,例如使用print函数
print(message);
},
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
3. 使用CachedResource加载和缓存资源
以下是一个示例,展示了如何加载和缓存图片资源:
import 'package:flutter/material.dart';
import 'package:cached_resource/cached_resource.dart';
import 'dart:async';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
CachedImage? _cachedImage;
bool _loading = true;
String? _error;
@override
void initState() {
super.initState();
// 加载并缓存图片
loadCachedImage();
}
Future<void> loadCachedImage() async {
setState(() {
_loading = true;
_error = null;
});
try {
_cachedImage = await CachedResource.imageFromUrl(
url: 'https://example.com/path/to/your/image.jpg',
key: 'unique_image_key', // 你可以使用任何唯一的键来标识这个资源
);
} catch (e) {
setState(() {
_error = e.toString();
_loading = false;
});
} finally {
if (_cachedImage != null) {
setState(() {
_loading = false;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cached Resource Example'),
),
body: Center(
child: _loading
? CircularProgressIndicator()
: _error != null
? Text('Error: $_error')
: Image.file(_cachedImage!.file),
),
);
}
}
4. 清理缓存(可选)
如果你需要清理缓存,可以调用CachedResource.clearCache()
方法:
void clearCache() async {
await CachedResource.clearCache();
print('Cache cleared');
}
你可以将这个方法绑定到一个按钮点击事件,以便用户手动清理缓存。
总结
以上示例展示了如何在Flutter应用中使用cached_resource
插件来加载和缓存网络资源。这可以显著提高应用的性能,尤其是在需要频繁加载网络图片或数据的情况下。你可以根据实际需求对代码进行扩展和修改。