ReactiveWidget 和 ReactiveValue 用于 Flutter
简单的状态管理 / 响应式状态跟踪,与那些非常复杂的常用 状态管理方法 相比,可以减少样板代码。
用法
在 pubspec.yaml 中依赖此 GitHub 项目
dependencies:
flutter:
sdk: flutter
flutter_reactive_widget:
git:
url: https://github.com/lukehutch/flutter_reactive_widget.git
ref: main
然后运行 flutter pub get。
导入库
import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';
使用 ReactiveValue<T> 声明您的状态(它扩展了 ValueNotifier<T>)
final counter = ReactiveValue<int>(0);
然后简单地将任何读取 counter.value 的代码包装在 ReactiveWidget 中
ReactiveWidget(
() => Text(
'${counter.value}',
style: const TextStyle(fontSize: 20),
),
),
在 ReactiveWidget 中对 counter.value 的简单引用会导致此 ReactiveWidget 开始监听 counter.value 的变化。(如果小部件被处置,此监听器会自动移除。)
任何修改 counter.value 的事件处理程序现在将触发 ReactiveWidget 使用新值进行重建。
持久化的 ReactiveValue 子类
通过使用 PersistentReactiveValue 而不是 ReactiveValue,您还可以跨应用程序重新启动持久化值。
首先在 main 中,您需要初始化 WidgetsFlutterBinding,然后需要调用 await PersistentReactiveValue.init()(它会从后端存储加载任何持久化的值)。
main() async {
// Both of the following lines are needed, in this order
WidgetsFlutterBinding.ensureInitialized();
await PersistentReactiveValue.init();
// Then run the app
runApp(App());
}
然后您可以使用 PersistentReactiveValue 而不是 ReactiveValue
final counter = PersistentReactiveValue<int>(/* key */ "counter", /* defaultValue */ 0);
如果 counter.value 之前从未设置过,它将被设置为默认值 0,但如果之前在应用程序的某个运行实例中设置过,则会使用键 "counter" 从 SharedPreferences 中恢复之前的值。
每当未来设置 counter.value 时,不仅会更新任何包装的 ReactiveWidget,而且新值还会使用相同的键异步写入到 SharedPreferences 持久化缓存中。
请注意,对于 PersistentReactiveValue<T>,T 不能是可空类型(T?),因为空值无法与 SharedPreferences 中不存在的值区分开来。例如,您可能需要为 PersistentReactiveValue<String> 存储空字符串而不是 null。此外,一旦设置了某个值,就没有办法将其取消设置以返回到默认值。
状态存储位置
这篇 Medium 文章 提供了关于如何使用 GetIt 来组织应用程序状态的绝佳建议。将此想法应用于 flutter_reactive_widget
main.dart
从 main 调用 setUpGetIt()
import 'package:my_app/pages/home_page.dart';
import './service_locator.dart';
main() async {
WidgetsFlutterBinding.ensureInitialized();
await PersistentReactiveValue.init();
// Register state singletons
setUpGetIt();
runApp(HomePage());
}
service_locator.dart
使用 GetIt 将所有包含状态的类注册为单例,每页一个状态类(即为页面 home_page.dart 创建 home_page_state.dart)
import 'package:my_app/pages/home_page_state.dart';
import 'package:get_it/get_it.dart';
void setUpGetIt() {
GetIt.instance.registerLazySingleton<HomePageState>(() => HomePageState());
}
pages/home_page_state.dart
定义每个状态类
import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';
/// The persistent state of [HomePage]
class HomePageState {
final count = PersistentReactiveValue<int>('count', 0);
}
pages/home_page.dart
使用 GetIt.instance<T>() 获取您需要从中读取状态的状态单例类实例
import 'package:my_app/pages/home_page_state.dart';
import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
// Get the state of the page
final _homePageState = GetIt.instance<HomePageState>();
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('HomeView'),
centerTitle: true,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ReactiveWidget(
() => Text(
'${_homePageState.count.value}',
style: const TextStyle(fontSize: 20),
),
),
IconButton(
icon: const Icon(Icons.plus_one),
onPressed: () {
_homePageState.count.value++;
},
),
],
),
);
}
}