Flutter乐观更新策略插件use_optimistic的使用
Flutter乐观更新策略插件use_optimistic的使用
一个易于使用的hook,用于乐观地更新通用状态,并通过accept
、acceptAs
或reject
来异步或同步地解决它。
文档
- 查看完整的示例以了解如何使用此hook管理整数状态。
- GitHub仓库在此处。
- 包在此处。
文档主要在包本身中通过doc-comments(即,在编辑器中悬停在包函数上会告诉您它们的作用)。首先,请查看上述完整的示例以开始使用。
简单用法
初始化hook
final UseOptimistic<int> useOptimistic = UseOptimistic<int>(initialState: 0);
确保您的小部件监听到状态变化
[@override](/user/override)
void initState() {
super.initState();
useOptimistic.addListener(() => setState(() => debugPrint("state changed to: ${useOptimistic.state}")));
}
确保当您的小部件被销毁时释放hook
[@override](/user/override)
void dispose() {
super.dispose();
useOptimistic.dispose();
}
乐观地更新状态
TextButton(
onPressed: () async {
Resolver r = useOptimistic.fn(
1, // 新值将传递给下面的函数
todo: (currentState, newValue) => currentState + newValue, // 乐观更新函数
undo: (currentState, oldValue) => currentState - oldValue, // 撤销函数
);
// 模拟API调用
await Future.delayed(const Duration(seconds: 1));
// 三种互斥的方式处理结果
r.acceptAs(2); // 先撤销原始操作,再使用新值进行乐观更新
r.accept(); // 接受原始的乐观更新
r.reject(); // 拒绝原始的乐观更新并撤销原始操作
},
child: const Text("乐观地增加1"),
),
您可以多次调用useOptimistic.fn(...)
,每次传递不同的todo
和undo
函数。这意味着您可以安全地一起调用多个独立的useOptimistic.fn(...)。但不意味着您可以有一个单一的
fn像这样(伪代码):
useOptimistic.fn( if x todo: () => {…} else todo: () => {…} ),其中
todo/
undo`函数根据条件渲染。
监听状态
Text("当前值: ${useOptimistic.state}"),
额外信息
- 该包始终欢迎改进、建议和添加!
- 我将尽快查看GitHub上的PR和Issue。
示例代码
import 'package:flutter/material.dart';
import 'package:use_optimistic/use_optimistic.dart'; // 导入包
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("useOptimistic hook 整数示例 🔥"),
),
body: const OptimisticUI(),
),
);
}
}
class OptimisticUI extends StatefulWidget {
const OptimisticUI({super.key});
[@override](/user/override)
OptimisticUIState createState() => OptimisticUIState();
}
class OptimisticUIState extends State<OptimisticUI> {
// 创建一个新的hook实例,设置其初始状态为0,并定义其类型为int
final UseOptimistic<int> useOptimistic = UseOptimistic<int>(initialState: 0);
[@override](/user/override)
void initState() {
super.initState();
// 监听状态的变化并更新UI
// 触发原始乐观更新和通过resolver.[someMethod]解决resolver
// 一旦调用[clearQueue]和[reset]也会触发
//
// 这很重要,除非您调用此方法,否则您的UI不会响应状态更改!!!
useOptimistic.addListener(() =>
setState(() => debugPrint("状态更改为: ${useOptimistic.state}")));
}
[@override](/user/override)
void dispose() {
// 移除监听器以避免内存泄漏
useOptimistic.dispose();
super.dispose();
}
// 创建一个新的resolver来处理某些整数值的乐观更新
Resolver<int> _addValue(int newValToFunctions) {
return useOptimistic.fn(
newValToFunctions, // 传递给下面函数的值
todo: (currentState, newValue) =>
currentState + newValue, // 乐观更新使用上面的值作为新的值
undo: (currentState, oldValue) =>
currentState - oldValue, // 撤销函数使用上面的值作为旧值
);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("当前值: ${useOptimistic.state}"),
const SizedBox(height: 40),
// 测试乐观更新的按钮
TextButton(
onPressed: () async {
final r = _addValue(1);
await Future.delayed(
const Duration(seconds: 1)); // 模拟服务器响应
// 假设服务器响应错误,所以我们想拒绝乐观更新
r.accept();
// 注意:多次调用r.[someMethod]没有效果;它只考虑第一次调用
r.reject();
},
child: const Text("乐观地增加1(异步接受)"),
),
// 使用新的.fn直接处理乐观更新
TextButton(
onPressed: () async {
final r = useOptimistic.fn(
5, // 传递给下面函数的值
todo: (currentState, newValue) =>
currentState ~/ newValue, // 乐观更新
undo: (currentState, oldValue) =>
currentState * oldValue, // 撤销函数(如所示,可以与[todo]完全相反)
);
await Future.delayed(
const Duration(seconds: 1)); // 模拟服务器响应
r.reject();
},
child: const Text("乐观地喂入5到自定义函数(异步拒绝)"),
),
TextButton(
onPressed: () {
useOptimistic
.fn(
1,
todo: (currentState, newValue) =>
currentState + newValue,
undo: (currentState, oldValue) =>
currentState - oldValue,
)
.accept(); // 再次,这会触发状态监听器两次 -> 一次为原始乐观更新,一次为resolver
},
child: const Text("乐观地增加1(同步接受)"),
),
TextButton(
onPressed: () async {
final r = _addValue(1);
await Future.delayed(
const Duration(seconds: 10)); // 模拟服务器响应
// 假设服务器响应错误,所以我们想拒绝乐观更新
r.reject();
},
child: const Text("乐观地增加1(异步拒绝)"),
),
TextButton(
onPressed: () async {
final r = _addValue(1);
await Future.delayed(
const Duration(seconds: 1)); // 模拟服务器响应
// 假设服务器响应2,所以我们想将初始+1更改为+2
r.acceptAs(2);
},
child: const Text("乐观地增加1(异步接受为2)"),
),
TextButton(
onPressed: () {
// 示例:将状态设置为10
useOptimistic.state = 10;
},
child: const Text("设置为10"),
),
TextButton(
// 清除待处理更新队列
onPressed: () => useOptimistic.clearQueue(),
child: const Text("清除队列"),
),
TextButton(
// 重置状态到初始状态
onPressed: () => useOptimistic.reset(),
child: const Text("重置"),
),
],
),
);
}
}
更多关于Flutter乐观更新策略插件use_optimistic的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter乐观更新策略插件use_optimistic的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter中使用use_optimistic
插件来实现乐观更新策略的示例代码。use_optimistic
插件允许你在等待异步操作(如网络请求)完成时,立即更新UI,从而提供即时的用户反馈。
首先,确保你已经在pubspec.yaml
文件中添加了use_optimistic
依赖:
dependencies:
flutter:
sdk: flutter
use_optimistic: ^最新版本号 # 请替换为实际的最新版本号
然后,运行flutter pub get
来安装依赖。
以下是一个简单的示例,展示了如何使用use_optimistic
来在Flutter中实现乐观更新:
import 'package:flutter/material.dart';
import 'package:use_optimistic/use_optimistic.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Optimistic Update Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final optimisticProvider = OptimisticProvider<int>((ref) {
// 初始值
return 0;
});
void _incrementOptimistically() async {
// 乐观地增加计数
optimisticProvider.update((value) => value + 1);
// 模拟一个异步操作,比如网络请求
await Future.delayed(Duration(seconds: 2));
// 确认更新(这里假设异步操作成功)
optimisticProvider.confirm();
}
void _resetOptimistic() async {
// 重置乐观更新(这里模拟异步操作失败的情况)
optimisticProvider.reset();
}
@override
Widget build(BuildContext context) {
final count = optimisticProvider.watch(context);
return Scaffold(
appBar: AppBar(
title: Text('Optimistic Update Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$count',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementOptimistically,
tooltip: 'Increment',
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
在这个示例中,我们创建了一个OptimisticProvider
来管理一个整数值。_incrementOptimistically
方法被调用时,我们首先乐观地增加计数(即不等待异步操作完成就更新UI),然后模拟一个异步操作(例如网络请求),并在操作完成后确认更新。如果异步操作失败,我们可以调用_resetOptimistic
方法来重置乐观更新。
注意:
optimisticProvider.update
方法用于乐观地更新状态。optimisticProvider.confirm
方法用于在异步操作成功后确认更新。optimisticProvider.reset
方法用于在异步操作失败时重置状态。
通过这种方式,你可以在Flutter中实现乐观更新策略,提高用户体验。