rxflare 1.4.0
rxflare: ^1.4.0 copied to clipboard
A high-performance reactive state management library for Flutter featuring automatic dependency tracking and granular field-level updates.
screenshot #
相关软件 #
音乐 https://github.com/msfm2018/localMusicPlay 树管理 https://github.com/msfm2018/simple_tree
the most basic usage (automatic dependency) #
final count = 0.obs;
Rx(() => Text("计数: ${count.value}"));
FloatingActionButton(
onPressed: () => count.value++,
child: Icon(Icons.add),
)
One Rx block listens to multiple values. #
final name = "张三".obs;
final age = 20.obs;
final score = 100.obs;
Rx(() => Text('${name.value},${age.value}岁,分数 ${score.value}'));
Map+Field Level Update (Core Competence) #
final user = {
"name": "张三",
"age": 25,
"avatar": "xxx"
}.obs;
// 只监听 name 变化
Rx(() => Text("姓名: ${user.getItem('name')}"));
// 只监听 age 变化
Rx(() => Text("年龄: ${user.getItem('age')}"));
// 精准更新某个字段
user.updateField("name", "李四"); // 仅 name 的 Rx 重绘
Demo 4:List + index accurate update #
final list = ["A", "B", "C"].obs;
Rx(() => Text("Item 1: ${list.getItem(1)}"));
list.updateField(1, "🔥B 已修改"); // 仅刷新第2项
Manual dependency mode (Rx.custom you wrote) #
class DemoPage5 extends StatelessWidget {
final count = 0.obs;
final name = "Tom".obs;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Rx.custom(
deps: [count], // 👈 只监听 count
builder: () {
return Text(
"count: ${count.value}, name: ${name.value}",
style: TextStyle(fontSize: 20),
);
},
),
),
floatingActionButton: Column(
children: [
FloatingActionButton(
onPressed: () => count.value++,
child: Icon(Icons.add),
),
FloatingActionButton(
onPressed: () => name.value = "Jerry",
child: Icon(Icons.person),
),
],
),
);
}
}
Field Level Dependency (Your Advanced Function) #
// final user = RxState<Map<String, dynamic>>({
final user = RxState<Map>({
"name": "Tom",
"age": 18
});
final nameUpper = computed(() {
return user.value["name"].toUpperCase();
});
print(nameUpper.value); // 输出 "TOM"
user.value = {...user.value, "name": "Jerry"};
print(nameUpper.value); // 输出 "JERRY"
The most basic computed #
final count = RxState<int>(1);
final doubleCount = computed(() => count.value * 2);
print(doubleCount.value); // 2
count.value = 5;
print(doubleCount.value); // 10(自动更新)
Multiple Dependencies #
final a = RxState<int>(2);
final b = computed(() => a.value * 2);
final c = computed(() => b.value + 1);
print(c.value); // 5
a.value = 10;
print(c.value); // 21
Dependency Dynamic Change #
final flag = RxState<bool>(true);
final a = RxState<int>(1);
final b = RxState<int>(100);
final result = computed(() {
if (flag.value) {
return a.value;
} else {
return b.value;
}
});
print(result.value); // 1(依赖 a)
flag.value = false;
print(result.value); // 100(依赖变成 b)
Chain computed #
final b = computed(() => a.value * 2);
final c = computed(() => b.value + 1);
print(c.value); // 5
a.value = 10;
print(c.value); // 21
RxEventBus #
Basic use (simplest) #
// 注册监听
RxEventBus.on<String>(
module: "user",
eventID: 1,
callback: (eventID, uuid, data) async {
print("收到事件: $data");
},
);
// 发送事件
RxEventBus.notify<String>(
module: "user",
eventID: 1,
data: "Hello EventBus",
);
Strongly typed (generic T) #
class User {
final String name;
User(this.name);
}
void main() {
RxEventBus.on<User>(
module: "user",
eventID: 2,
callback: (id, uuid, user) async {
print("用户: ${user.name}");
},
);
RxEventBus.notify<User>(
module: "user",
eventID: 2,
data: User("Tom"),
);
}
Cancel listening (off) #
late EventCallback<String> cb;
void main() {
cb = (id, uuid, data) async {
print("监听: $data");
};
RxEventBus.on<String>(
module: "test",
eventID: 1,
callback: cb,
);
RxEventBus.notify(module: "test", eventID: 1, data: "第一次");
// 移除
RxEventBus.off(
module: "test",
eventID: 1,
callback: cb,
);
RxEventBus.notify(module: "test", eventID: 1, data: "第二次");
}
Bulk removal using Token (recommended) #
void main() {
final token = EventToken();
RxEventBus.on<String>(
module: "chat",
eventID: 1,
token: token,
callback: (id, uuid, data) async {
print("A: $data");
},
);
RxEventBus.on<String>(
module: "chat",
eventID: 1,
token: token,
callback: (id, uuid, data) async {
print("B: $data");
},
);
RxEventBus.notify(module: "chat", eventID: 1, data: "hello");
// 一键移除
RxEventBus.offByToken(token);
RxEventBus.notify(module: "chat", eventID: 1, data: "world");
}
Sticky event (you can also receive it after registration) #
void main() {
// 先发送(sticky)
RxEventBus.notify<String>(
module: "config",
eventID: 1,
data: "配置已加载",
sticky: true,
);
// 后注册仍然会收到
RxEventBus.on<String>(
module: "config",
eventID: 1,
sticky: true,
callback: (id, uuid, data) async {
print("收到 sticky: $data");
},
);
}
6. 优先级(high / normal / low)
void main() {
RxEventBus.on<String>(
module: "priority",
eventID: 1,
callback: (id, uuid, data) async {
print("执行: $data");
},
);
RxEventBus.notify(
module: "priority",
eventID: 1,
data: "普通",
priority: EventPriority.normal,
);
RxEventBus.notify(
module: "priority",
eventID: 1,
data: "高优先级",
priority: EventPriority.high,
);
RxEventBus.notify(
module: "priority",
eventID: 1,
data: "低优先级",
priority: EventPriority.low,
);
}
Serial vs parallel #
RxEventBus.on<String>(
module: "task",
eventID: 1,
callback: (id, uuid, data) async {
await Future.delayed(Duration(milliseconds: 500));
print("任务1完成");
},
);
RxEventBus.on<String>(
module: "task",
eventID: 1,
callback: (id, uuid, data) async {
await Future.delayed(Duration(milliseconds: 500));
print("任务2完成");
},
);
// 并行(默认)
RxEventBus.notify(
module: "task",
eventID: 1,
data: "",
parallel: true,
);
// 串行
RxEventBus.notify(
module: "task",
eventID: 1,
data: "",
parallel: false,
);
RxFuture #
Load User Information Page #
late RxFuture<String> userRx;
userRx = RxFuture(() async {
await Future.delayed(const Duration(seconds: 2));
return "用户数据加载成功";
});
if (userRx.isInitialLoading) return const CircularProgressIndicator();
if (userRx.hasError) return Text("错误: ${userRx.error}");
Text(userRx.data ?? "");
RxObjMgr + RxParent #
最基础用法(手动 put / find)
class UserController {
String name = "Tom";
}
void main() {
// 注册
RxObjMgr.put(UserController());
// 获取
final c = RxObjMgr.find<UserController>();
print(c.name); // Tom
}
2. 懒加载(lazyPut)
class ApiService {
ApiService() {
print("ApiService 创建了");
}
}
void main() {
RxObjMgr.lazyPut<ApiService>(() => ApiService());
// 此时还没创建
final api = RxObjMgr.find<ApiService>();
// 👉 这里才真正创建
final api2 = RxObjMgr.find<ApiService>();
// 👉 不会重复创建(单例)
}
3. 多实例(name 区分)
class Counter {
int value = 0;
}
void main() {
RxObjMgr.put(Counter(), name: "A");
RxObjMgr.put(Counter(), name: "B");
final a = RxObjMgr.find<Counter>(name: "A");
final b = RxObjMgr.find<Counter>(name: "B");
a.value = 10;
b.value = 20;
print(a.value); // 10
print(b.value); // 20
}
4 Flutter 实战
class CounterController {
int count = 0;
void increment() {
count++;
}
void dispose() {
print("Controller 被释放");
}
}
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RxParent<CounterController>(
dependency: CounterController(),
child: const CounterView(),
);
}
}
class CounterView extends StatefulWidget {
const CounterView({super.key});
@override
State<CounterView> createState() => _CounterViewState();
}
class _CounterViewState extends State<CounterView> {
late CounterController controller;
@override
void initState() {
super.initState();
controller = RxObjMgr.find<CounterController>();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("DI 示例")),
body: Center(
child: Text("count: ${controller.count}"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
controller.increment();
});
},
child: const Icon(Icons.add),
),
);
}
}
@override
void dispose() {
final dynamic instance = RxObjMgr.find<T>(name: widget.name);
instance.dispose?.call(); // 自动调用
RxObjMgr.delete<T>(name: widget.name);
}
多页隔离
RxParent<CounterController>(
name: "pageA",
dependency: CounterController(),
child: PageA(),
)
RxParent<CounterController>(
name: "pageB",
dependency: CounterController(),
child: PageB(),
)
获取
final cA = RxObjMgr.find<CounterController>(name: "pageA");
final cB = RxObjMgr.find<CounterController>(name: "pageB");
结合 RxFuture(高级组合)
class UserController {
late RxFuture<String> userRx;
UserController() {
userRx = RxFuture(() async {
await Future.delayed(Duration(seconds: 1));
return "用户数据";
});
}
void dispose() {
userRx.dispose();
}
}
class UserPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RxParent<UserController>(
dependency: UserController(),
child: const UserView(),
);
}
}
使用
class UserView extends StatefulWidget {
const UserView({super.key});
@override
State<UserView> createState() => _UserViewState();
}
class _UserViewState extends State<UserView> {
late UserController c;
@override
void initState() {
super.initState();
c = RxObjMgr.find<UserController>();
c.userRx.listen(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
if (c.userRx.isInitialLoading) {
return const Center(child: CircularProgressIndicator());
}
return Center(
child: Text(c.userRx.data ?? ""),
);
}
}
#
final count = RxState<int>(0);
// 监听
final cancel = count.listen((v) {
print("count: $v");
});
// 更新
count.value = 1;
count.update(2);
// 取消监听
cancel();
2. 带来源 ID(调试神器)
final state = RxState<int>(0, name: "counter");
state.listenWithId((value, id) {
print("value: $value, 来自: $id");
});
state.value = 10;
state.refresh(); // 手动触发
3. Map 精准监听(🔥核心能力)
final user = RxState<Map<String, dynamic>>({
"name": "Tom",
"age": 20,
});
// 只监听 name
final cancel = user.listenByKey("name", (v) {
print("name 变了: $v");
});
// 更新 name
user.updateField("name", "Jerry");
// 更新 age(不会触发)
user.updateField("age", 30);
4. List 精准监听
final list = RxState<List<int>>([1, 2, 3]);
list.listenByKey(1, (v) {
print("index 1: $v");
});
list.updateField(1, 999); // ✅ 触发
list.updateField(0, 111); // ❌ 不触发
5. 条件监听(listenWhere)
final data = RxState<Map<String, dynamic>>({
"score": 50,
});
data.listenWhere(
(map) => map["score"] >= 60,
(v) {
print("是否及格: $v");
},
);
data.updateField("score", 70);
6. 局部更新 vs 全局更新
final user = RxState<Map<String, dynamic>>({
"name": "Tom",
"age": 20,
});
user.listen((v) {
print("全局更新: $v");
});
user.listenByKey("name", (v) {
print("name 更新: $v");
});
// 默认:只触发 field
user.updateField("name", "Jerry");
// 强制触发全局
user.updateField("name", "Jack", notifyGlobal: true);
7. Flutter UI 实战
final counter = RxState<int>(0);
class RxDemoPage extends StatefulWidget {
@override
State<RxDemoPage> createState() => _RxDemoPageState();
}
class _RxDemoPageState extends State<RxDemoPage> {
late VoidCallback cancel;
@override
void initState() {
super.initState();
cancel = counter.listen((_) {
setState(() {});
});
}
@override
void dispose() {
cancel();
counter.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("RxState Demo")),
body: Center(
child: Text("count: ${counter.value}"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
counter.value++;
},
child: const Icon(Icons.add),
),
);
}
}
8. Form scene (Map+accurate update)
final form = RxState<Map<String, dynamic>>({
"username": "",
"password": "",
});
监听单字段:
form.listenByKey("username", (v) {
print("用户名输入: $v");
});
更新
form.updateField("username", "admin");
9. Advanced combination (similar to computed)
final a = RxState<int>(1);
final b = RxState<int>(2);
// 假设你有 RxComputed
// final sum = RxComputed(() => a.value + b.value);
route #
Define and register routes #
rxr.register({
'/home': RxDef(builder: () => const HomePage(), path: '/home'),
'/detail/:id': RxDef(builder: () => const DetailPage(), path: '/detail/:id'),
});
// 跳转
rxr.to('/detail/123?type=hot', arguments: MyData());
// 获取参数
final id = rxr.param('id'); // 路径参数
final type = rxr.queryItem('type'); // query 参数
final obj = rxr.args<MyData>(); // 自定义对象
返回数据
final result = await rxr.to('/edit');
rxr.back(result: "保存成功");
Jump and parameter acquisition #
// 跳转
rxr.to('/detail/123?type=premium', arguments: MyObject());
// 目标页获取参数
final id = rxr.param('id'); // '123'
final type = rxr.queryItem('type'); // 'premium'
final obj = rxr.args<MyObject>(); // 获取自定义对象
Return and return the results. #
// 发起跳转并等待
final result = await rxr.to('/settings');
// 目标页返回
rxr.back(result: 'Saved!');
RxBuilder #
RxBuilder(
builder: (_) {
return ListView.builder(
itemBuilder: (context, index) {
return RxBuilder(
builder: (_) {
final isSelected = selectedIndex.value == index;
return ListTile(
title: Text(items[index]),
tileColor: isSelected ? Colors.orange[100] : null,
);
},
);
},
);
},
);