Flutter响应式编程插件flutter_reactive_widget的使用
Flutter响应式编程插件flutter_reactive_widget的使用
已弃用
我正在弃用此库,因为我发现了一个在Flutter中创建响应式UI的更简单且更好的机制:请改用flutter_reactive_value
库。
此flutter_reactive_widget
库的文档和代码仍会托管在此处,但此代码将不再进行进一步开发。
使用
此库提供了一种在Flutter中创建响应式UI的简单机制。
1. 声明状态
使用ReactiveValue<T>
(继承自ValueNotifier<T>
)声明您的状态:
final counter = ReactiveValue<int>(0);
2. 包装需要对counter.value
变化作出反应的代码
使用ReactiveWidget
(它接受一个零参数lambda,在ReactiveWidget
的build
方法中调用该lambda)包装任何需要对counter.value
的变化作出反应的代码。
如果在ReactiveWidget
的build()
方法运行时读取了counter.value
,那么ReactiveWidget
将开始监听counter.value
的变化。(如果该部件被销毁,此监听器将自动移除。)
ReactiveWidget(
() => Text('${counter.value}'),
),
3. 修改counter.value
的事件处理程序将触发ReactiveWidget
重新构建
修改counter.value
的事件处理程序现在将通过在后帧回调中调度setState
调用来触发ReactiveWidget
重新构建。
IconButton(
icon: const Icon(Icons.plus_one),
onPressed: () {
counter.value++;
},
),
counter.value
可以在除build
方法之外的任何地方修改(因为build
方法不应该改变状态)。
添加库依赖
flutter_reactive_widget
托管在pub.dev上。
要能够导入该库,你需要在pubspec.yaml
中添加对该库的依赖(如果你想要控制版本,可以将any
替换为最新版本),然后运行flutter pub get
:
dependencies:
flutter:
sdk: flutter
flutter_reactive_widget: any
在你的代码中导入该库:
import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';
持久化状态的子类PersistentReactiveValue
ReactiveValue
每次应用重启时都会重置为其初始值。你可以通过使用PersistentReactiveValue
而不是ReactiveValue
来持久化值。
首先,在main
函数中,你需要初始化WidgetsFlutterBinding
,然后需要调用await initPersistentReactiveValue()
(定义在flutter_reactive_widget.dart
中),这会启动SharedPreferences
并从存储中加载任何持久化的值。
main() async {
// 需要按以下顺序执行这两行代码
WidgetsFlutterBinding.ensureInitialized();
await initPersistentReactiveValue();
// 然后运行应用
runApp(App());
}
然后你可以使用PersistentReactiveValue
而不是ReactiveValue
:
final counter = PersistentReactiveValue<int>(
/* key */ 'counter', /* defaultValue */ 0);
counter.value
如果没有被设置过,则会被设置为默认值0
;但如果在之前的某个应用运行中已经设置了值,那么这个值将从SharedPreferences
中恢复,使用键’counter’
。
每当在未来设置counter.value
时,不仅任何包裹的ReactiveWidget
会被更新,而且新值还会异步写入到SharedPreferences
持久化缓存中,使用相同的键。
可以存储null值的子类PersistentReactiveNullableValue
注意,对于PersistentReactiveValue<T>
,T
不能是可空类型(T?
),因为null值无法与SharedPreferences
中不存在的值区分开来。
如果你希望能够在SharedPreferences
中存储null值(这相当于尝试设置null值时从SharedPreferences
中删除键),则可以使用PersistentReactiveNullableValue<T?>
。对于此类,defaultValue
是可选的。
用于验证的子类ValidatingReactiveValue
ValidatingReactiveValue
是ReactiveValue
的一个子类,具有一个额外的字段validationError
,它本身是一个ReactiveValue<String?>
。每当ValidatingReactiveValue
的值发生变化时,validationError
字段会通过调用传递给ValidatingReactiveValue
构造函数的validate
函数来更新。例如:
final age = ValidatingReactiveValue<int?>(null,
(a) => a == null ? 'Please specify age' : null);
// 现在你可以在一个`ReactiveWidget`中监听`age.validationError`或`age.value`
手动通知深层值的变化
如果你创建了final set = ReactiveValue<Set<String>>({});
然后调用了set.value.add(‘abc’)
,set
的监听器不会收到更改的通知,因为引用本身(即set.value
)没有改变。在这种情况下,你可以手动调用监听器,例如:
_addFlag(bool flag) {
bool changed = flag ? set.value.add('flag') : set.value.remove('flag');
if (changed) {
set.notifyListeners();
}
}
在StatefulWidget的State.dispose()方法中移除ReactiveValue监听器
如果你在一个StatefulWidget
的State<T>
对象的字段中实例化了一个ReactiveValue
,确保你的State<T>
的dispose()
方法调用了ReactiveValue
的dispose()
方法来移除所有监听器,当部件被销毁时,以防止内存泄漏。
生命周期和状态存储位置
如果你想让ReactiveValue
在整个应用生命周期内存在,可以参考这篇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 initPersistentReactiveValue();
// 注册状态单例(定义在service_locator.dart)
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';
final getIt = GetIt.instance;
void setUpGetIt() {
getIt.registerLazySingleton<HomePageState>(() => HomePageState());
}
pages/home_page_state.dart
定义每个状态类:
import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';
/// HomePage的持久状态
class HomePageState {
final count = PersistentReactiveValue<int>('count', 0);
}
pages/home_page.dart
使用GetIt.instance<T>()
(或getIt<T>
,如果你导入了service_locator.dart
)获取你需要读取状态的状态单例类实例:
import 'package:my_app/pages/home_page_state.dart';
import 'package:flutter_reactive_widget/flutter_reactive_widget.dart';
import 'package:flutter/material.dart';
import './service_locator.dart';
// 获取页面的状态
final _homePageState = getIt<HomePageState>();
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
[@override](/user/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++;
},
),
],
),
);
}
}
更多关于Flutter响应式编程插件flutter_reactive_widget的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter响应式编程插件flutter_reactive_widget的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用Flutter响应式编程插件flutter_reactive_widget
的代码案例。这个插件使得在Flutter中进行响应式编程变得更加简单和直观。
首先,确保你已经在pubspec.yaml
文件中添加了flutter_reactive_widget
依赖:
dependencies:
flutter:
sdk: flutter
flutter_reactive_widget: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
以下是一个简单的示例,展示如何使用flutter_reactive_widget
进行响应式编程。在这个例子中,我们将使用ReactiveTextField
来创建一个响应式文本字段,并实时显示输入内容。
import 'package:flutter/material.dart';
import 'package:flutter_reactive_ble/flutter_reactive_ble.dart'; // 注意:实际包名可能有所不同,这里仅作为示例
import 'package:reactive_forms/reactive_forms.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _formGroup = fb.group({
'username': ['', Validators.required],
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Reactive Widgets Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ReactiveForm(
formGroup: _formGroup,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ReactiveTextField<String>(
formControlName: 'username',
decoration: InputDecoration(
labelText: 'Username',
),
),
SizedBox(height: 16),
Text(
'You entered: ${_formGroup.value['username'] ?? ''}',
style: TextStyle(fontSize: 18),
),
],
),
),
),
);
}
}
在这个例子中,我们做了以下几件事情:
-
创建表单组:使用
fb.group
创建一个表单组,并定义了一个名为username
的表单控件,它有一个初始值和一个验证器(Validators.required
)。 -
构建UI:使用
ReactiveForm
包装表单,并在其内部使用ReactiveTextField
创建一个响应式文本字段。formControlName
属性将文本字段与表单组中的username
表单控件绑定。 -
显示输入内容:通过访问
_formGroup.value['username']
实时显示用户输入的内容。
注意:flutter_reactive_widget
插件实际上依赖于reactive_forms
库来处理表单控件和验证。因此,确保你也添加了reactive_forms
依赖。
dependencies:
reactive_forms: ^x.y.z # 请替换为最新版本号
这个示例展示了如何使用flutter_reactive_widget
(通过reactive_forms
)进行基本的响应式表单编程。你可以根据需求扩展这个示例,添加更多的表单控件和验证逻辑。