Flutter响应式编程插件rx_observable的使用
Flutter响应式编程插件rx_observable的使用
Simple reactive variables and widgets. 类似于Livedata/observable/mobx,但无需代码生成和复杂的样板代码。
适用于MVVM等模式。
特性
创建反应变量,监听它们并更新UI。
使用方法
定义变量的方法如下:
var text = "Hello".obs;
使用Observer小部件来订阅更改:
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
/// 直接使用Observer小部件更新UI值
Observer(text, (v) => Text(v)),
/// 使用扩展方法创建相同的Observer小部件
text.observer((v) => Text(v)),
/// 使用大构建版本
Observer.builder(
observable: text,
builder: (context, v) {
return Text(v);
}
)
],
),
);
更新值的方法如下:
text.value = "GoodBye";
监听的方法如下:
text.listen((v) {
print("New value is $v");
});
关闭的方法如下:
text.close();
其他信息
更多示例:
// 在Observer中监听两个或三个observables
Observer3.builder(
observable: text,
observable2: text2,
observable3: text3,
builder: (context, v1, v2, v3) {
return Text("$v1 $v2 $v3");
}
),
// 所有构造函数结果相同
var test1 = Observable(25);
var test2 = Observable<int>(25);
var test3 = Obs(25);
var test4 = 25.obs;
var test5 = ObservableInt(25);
var test6 = ObservableReadOnly(25); /// 只能读取此值
test1.listen((v) {
if (kDebugMode) { print(v); }
});
/// 不更新UI的情况下监听observable
/// 也可以查看ObservableConsumer小部件以获取两者
var widgetListener = ObservableListener(
observable: test1,
listener: (v, context) {
if (kDebugMode) { print(v); }
},
child: const SizedBox(),
);
还可以检查RxSubsMixin,以便轻松处理您的反应变量、订阅和流的关闭(例如在viewModel/bloc/store/repository中)。
与状态概念结合使用
您可以将这种方法与状态概念结合使用,即使_bloc创作者告诉你状态必须是不可变的等等。
只需使用这个简单技巧,并确保始终关闭您的反应变量(使用RxSubsMixin帮助),就不会有问题发生:
/// 创建一些viewModel/Bloc样式的类,带自动清理的mixin和可清理接口
class ViewModelExample with RxSubsMixin implements IDisposable {
/// 定义用于监听状态的反应变量。就像Bloc模式一样。
Observable<T> state = LoadingState();
/// 简单示例变量。你可以将状态概念与简单变量混合使用或不使用,这取决于你。
var title = "Hello".obs;
/// 这里是魔法。为某个列表定义一个私有变量。它将在状态中使用。
final _contactsList = Observable<List<Contact>>([]);
ViewModelExample() {
/// 自动清理这些变量
regs([state, title, _contactsList]);
}
void loadContacts() {
/// ...做一些魔法从任何地方获取异步数据
/// 然后将它的值作为指针传递给状态,因为它不是简单类型。
state.value = LoadedState(contacts: _contactsList);
}
}
/// 状态本身。哇!你有一个带有反应变量的状态,但它不会导致任何泄漏(可能?)
/// 因为实际值在ViewModelExample中,而状态中只有指向它的链接。
/// 当然,由于并发访问列表可能会出现一些问题,但在我的实践中从未发生过。
class LoadedState extends BaseState {
final ObservableReadOnly<List<Contact>> contacts;
LoadedState({required this.contacts});
}
基本UI示例:
var vm = context.read<ViewModelExample>();
Observer(vm.state, (vmState) {
switch (vmState) {
case LoadingState():
return const LoadingWidget();
case LoadedState():
return Observer(vmState.contacts, (vmContacts) {
if (vmContacts.isEmpty) {
return EmptyWidget();
} else {
return ListWidget(vmContacts);
}
});
case ErrorState():
return ErrorWidget();
}
})
为什么比mobX、Bloc、GetX更好?
MobX的弱点在于代码生成。在某些情况下,这可能导致开发过程中出现问题,例如处理最终的延迟反应变量可能很困难。
Bloc有太多的样板代码,管理和整个状态涉及太多工作。它需要刷新整个状态才能改变一个值。
另一方面,GetX(或Get)包含太多功能,可能存在bug,核心复杂。
示例代码
以下是完整的示例代码:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:rx_observable/rx_observable.dart';
import 'package:rx_observable/widgets.dart';
import 'example_screen.dart';
void main() {
// 所有构造函数结果相同
var test1 = Observable(25);
var test2 = Observable<int>(25);
var test3 = Obs(25);
var test4 = 25.obs;
var test5 = ObservableInt(25);
var test6 = ObservableReadOnly(25); /// 只能读取此值
test1.close();
test2.close();
test3.close();
test4.close();
test5.close();
test6.close();
runApp(const ExampleApp());
}
class ExampleApp extends StatefulWidget {
const ExampleApp({super.key});
[@override](/user/override)
State<ExampleApp> createState() => _ExampleAppState();
}
class _ExampleAppState extends State<ExampleApp> {
var test1 = Observable(25);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Rx Observable Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
/// 不更新UI的情况下监听observable
/// 也可以查看ObservableConsumer小部件以获取两者
home: ObservableListener(
observable: test1,
listener: (v, context) {
if (kDebugMode) { print(v); }
},
/// 查看其他示例在[ExampleScreen]
child: const ExampleScreen()
),
);
}
}
更多关于Flutter响应式编程插件rx_observable的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter响应式编程插件rx_observable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
rx_observable
并不是 Flutter 官方或社区中广泛使用的响应式编程插件。在 Flutter 中,最常用的响应式编程库是 RxDart,它是基于 Dart 语言的响应式扩展(Reactive Extensions)实现。RxDart 提供了丰富的操作符和工具,用于处理异步数据流和事件流。
如果你正在寻找一个响应式编程的解决方案,建议使用 RxDart。以下是关于如何在 Flutter 中使用 RxDart 的基本指南:
1. 添加 RxDart 依赖
在 pubspec.yaml
文件中添加 RxDart 依赖:
dependencies:
flutter:
sdk: flutter
rxdart: ^0.27.7 # 请使用最新版本
然后运行 flutter pub get
安装依赖。
2. 使用 RxDart 的基本概念
RxDart 的核心是 Observable(可观察对象),它代表一个异步数据流。你可以使用 RxDart 的操作符来转换、过滤和组合这些数据流。
以下是一个简单的示例:
import 'package:rxdart/rxdart.dart';
void main() {
// 创建一个 Observable
final observable = Observable.fromIterable([1, 2, 3, 4, 5]);
// 使用操作符转换数据流
observable
.map((value) => value * 2) // 将每个值乘以 2
.where((value) => value > 5) // 过滤掉小于等于 5 的值
.listen((value) {
print(value); // 输出: 6, 8, 10
});
}
3. 在 Flutter 中使用 RxDart
RxDart 通常与 Flutter 的 StreamBuilder
或 StatefulWidget
结合使用,以实现响应式 UI。
以下是一个简单的 Flutter 示例:
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
class CounterPage extends StatefulWidget {
[@override](/user/override)
_CounterPageState createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
final BehaviorSubject<int> _counterSubject = BehaviorSubject.seeded(0);
void _incrementCounter() {
_counterSubject.add(_counterSubject.value + 1);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('RxDart Counter')),
body: Center(
child: StreamBuilder<int>(
stream: _counterSubject.stream,
builder: (context, snapshot) {
return Text(
'Counter: ${snapshot.data ?? 0}',
style: TextStyle(fontSize: 24),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: Icon(Icons.add),
),
);
}
[@override](/user/override)
void dispose() {
_counterSubject.close(); // 关闭 Subject
super.dispose();
}
}
void main() => runApp(MaterialApp(
home: CounterPage(),
));