Flutter响应式数据管理插件reactive_data_manager的使用
Flutter响应式数据管理插件reactive_data_manager的使用
一个为Flutter提供的强大响应式数据管理系统,内置缓存、乐观更新和错误处理功能。
特性
- 🔄 响应式数据流
- 💾 自动缓存
- ⚡ 乐观更新
- 🔍 数据过滤
- ❌ 错误处理
- 🧹 自动资源清理
安装
在pubspec.yaml
文件中添加以下依赖:
dependencies:
reactive_data_manager: ^1.0.0
基本用法
// 创建管理器实例
final userManager = ReactiveDataManager<int, User>(
fetcher: (id) => fetchUserFromApi(id),
updater: (id, user) => updateUserInApi(id, user),
);
// 获取数据流
Stream<User?> userStream = userManager.getStream(userId);
// 获取或刷新数据
User user = await userManager.getData(userId);
// 强制刷新
User freshUser = await userManager.getData(userId, forceRefresh: true);
// 更新数据
await userManager.updateData(userId, updatedUser);
高级用法
带有数据过滤
ReactiveDataManager<String, Data>(
fetcher: fetchData,
updater: updateData,
fetchFilter: (key, data) {
// 过滤获取的数据
return data.isValid ? data : null;
},
updateFilter: (key, result) {
// 过滤更新结果
return result.success ? result.data : null;
},
);
在Flutter小部件中使用
StreamBuilder<User?>(
stream: userManager.getStream(userId),
builder: (context, snapshot) {
if (snapshot.hasError) {
return ErrorWidget(snapshot.error!);
}
if (!snapshot.hasData) {
return LoadingWidget();
}
return UserWidget(user: snapshot.data!);
},
);
清理
当不再需要管理器时,记得释放它:
[@override](/user/override)
void dispose() {
userManager.dispose();
super.dispose();
}
完整示例代码
import 'package:flutter/material.dart';
import 'package:reactive_data_manager/reactive_data_manager.dart';
void main() {
runApp(const MyApp());
}
// 示例数据类
class User {
final int id;
final String name;
final int age;
User({required this.id, required this.name, required this.age});
User copyWith({String? name, int? age}) {
return User(
id: id,
name: name ?? this.name,
age: age ?? this.age,
);
}
[@override](/user/override)
String toString() => 'User(id: $id, name: $name, age: $age)';
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const ReactiveShowcase(),
);
}
}
class ReactiveShowcase extends StatefulWidget {
const ReactiveShowcase({super.key});
[@override](/user/override)
State<ReactiveShowcase> createState() => _ReactiveShowcaseState();
}
class _ReactiveShowcaseState extends State<ReactiveShowcase> {
late final ReactiveDataManager<int, User> _userManager;
final _nameController = TextEditingController();
final List<int> userIds = List.generate(100, (id) => id);
[@override](/user/override)
void initState() {
super.initState();
_userManager = ReactiveDataManager<int, User>(
fetcher: _fetchUser,
updater: _updateUser,
);
// 预取所有用户
for (final id in userIds) {
_userManager.getData(id);
}
}
Future<User> _fetchUser(int id) async {
await Future.delayed(const Duration(seconds: 1));
return User(
id: id,
name: 'User $id',
age: 20 + id,
);
}
Future<User> _updateUser(int id, User user) async {
await Future.delayed(const Duration(milliseconds: 500));
return user;
}
[@override](/user/override)
void dispose() {
_nameController.dispose();
_userManager.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('示例')),
body: ListView.builder(
itemCount: userIds.length,
itemBuilder: (context, index) {
final userId = userIds[index];
return Card(
margin: const EdgeInsets.all(8),
child: StreamBuilder<User?>(
stream: _userManager.getStream(userId),
builder: (context, snapshot) {
if (snapshot.hasError) {
return ListTile(
title: Text('错误: ${snapshot.error}'),
trailing: IconButton(
icon: const Icon(Icons.refresh),
onPressed: () =>
_userManager.getData(userId, forceRefresh: true),
),
);
}
if (!snapshot.hasData) {
return const ListTile(
title: Center(child: CircularProgressIndicator()),
);
}
final user = snapshot.data!;
return ListTile(
title: Text('姓名: ${user.name}'),
subtitle: Text('年龄: ${user.age}'),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () => _showEditDialog(user),
),
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () =>
_userManager.getData(userId, forceRefresh: true),
),
],
),
);
},
),
);
},
),
);
}
Future<void> _showEditDialog(User user) async {
_nameController.text = user.name;
return showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('编辑用户 ${user.id}'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: _nameController,
decoration: const InputDecoration(labelText: '姓名'),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消'),
),
TextButton(
onPressed: () {
final updatedUser = user.copyWith(name: _nameController.text);
_userManager.updateData(user.id, updatedUser);
Navigator.pop(context);
},
child: const Text('保存'),
),
],
),
);
}
}
更多关于Flutter响应式数据管理插件reactive_data_manager的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复