Flutter可控制组件插件controllable_flutter的使用
controllable_flutter 
轻松且方便的状态管理。将您的业务逻辑与UI层分离。
⚠️ 注意:这是一个alpha版本。文档尚未完成,后续会扩展和更新。
快速概览
发送状态更新
@override
void onUpdateName(String newName) {
emitWith(name: newName);
}
读取状态
Text(context.myController.state.name);
监听状态变化
Text(context.myController.state.watch.name);
触发事件
TextButton(
onPressed: () => context.myController.raiseEvent.updateName('New name'),
child: Text('触发更新名称事件'),
);
更多功能
更多详细信息,请参阅下方内容。
目录
示例
设置
在pubspec.yaml
中添加依赖:
dependencies:
controllable_flutter:
dev_dependencies:
build_runner:
controllable_generator:
首先,声明您的State
和Event
类。为了简单起见,我们将使用int
作为副作用,但实际上它可以是任何类甚至枚举。
状态
将状态所需的数据字段作为getter声明。这些将在UI和控制器级别上可用。
part of 'home_controller.dart';
abstract class HomeState extends XState {
String get name;
String? get address;
}
事件
描述UI可以触发的事件方法。这些将被UI用于触发控制器操作。
part of 'home_controller.dart';
abstract class HomeEvent extends XEvent {
void updateName(String newName);
void updateAddress(String newAddress);
void updateCounter(int counter);
}
声明控制器类
/* 导入 */
part 'home_controller.x.dart';
part 'home_event.dart';
part 'home_state.dart';
@XControllable<HomeEvent>()
class HomeController extends XController<HomeState> with _$HomeController {
@override
HomeState createInitialState() {
// 我们稍后会填充它。
}
}
运行构建工具
flutter pub run build_runner build
使用
填充控制器
生成了一个包含设置和扩展的文件。现在您可以填写控制器的详细信息:
@XControllable<HomeEvent>()
class HomeController extends XController<HomeState> with _$HomeController {
@override
HomeState createInitialState() {
// 使用以下方法创建控制器的初始状态。
// 参数与您在HomeState类中声明的相同。
return createHomeState(name: 'something');
}
// 下面的方法称为事件。这些将从UI级别触发。
// 它们基于HomeEvent类自动生成。
// 注意,updateName方法变成了onUpdateName等。
@override
void onUpdateAddress(String newAddress) {
// 使用emitWith向UI传递具有更新字段的新状态。
emitWith(address: newAddress);
}
@override
void onUpdateName(String newName) {
emitWith(name: newName);
}
@override
void onUpdateCounter(int counter) {
// 使用fireEffect触发UI层可以捕获的效果
// 使用XListener小部件。
// 然后它可以导航到另一个页面,显示一个提示等。
fireEffect(counter);
}
}
界面
提供HomeController
:
return XProvider(
create: (context) => HomeController(),
child: const HomeBody(),
);
在HomeBody
中访问字段:
final controller = context.homeController;
return Column(
children: [
Text(controller.state.watch.name),
Text(controller.state.watch.address),
TextButton(
// 调用控制器的onUpdateName方法。
onPressed: () => controller.raiseEvent.updateName('New Name'),
child: Text('将名称设置为"New Name"'),
),
],
);
watch
语句将使给定BuildContext
的小部件在相应字段更改时重建。因此,在上面的示例中,每当执行emitWith(name: any)
或emitWith(address: any)
时,树都会重新构建。但我们希望避免不必要的重建,对吧?将文本移动到单独的小部件中!或者将其包装在构建器中:
return Column(
children: [
Builder(
// 只有当名称更改时才会重建
// 因为这个`context`现在只与此部分树相关!
builder: (context) => Text(context.homeController.state.watch.name)
),
Builder(
// 只有当地址更改时才会重建
// 因为这个`context`现在只与此部分树相关!
builder: (context) => Text(context.homeController.state.watch.address)
),
// 按钮不会在名称或地址未更改时重建
TextButton(
onPressed: () => context.homeController.raiseEvent.updateName('New Name'),
child: Text('将名称设置为"New Name"'),
),
],
);
如果只想简单地读取字段而不观察它,只需不使用watch
访问它:
onPressed: () => print(context.homeController.state.name),
如何操作
发送新状态
在您的控制器中,使用emitWith
向UI发送新状态。调用emitWith(yourField: newValue)
以更新yourField
。
监听或读取状态
使用context.controller.state.watch.*
监听状态字段的更新。
使用context.controller.state.*
简单地读取状态字段。
触发事件
要在UI级别上执行某些业务逻辑,执行context.yourController.raiseEvent.yourEvent
。这将在控制器中执行相应的方法。
触发副作用
副作用用于执行UI操作。导航到另一个屏幕、显示对话框或提示、验证表单字段等——这就是副作用的作用。
在您的控制器中,执行:
fireEffect(data);
监听副作用
使用XListener
小部件来监听由控制器触发的副作用。
XListener(
streamable: context.homeController,
listener: (context, effect) {
// 在UI级别执行所需的操作。
print(effect); // 或者只是打印效果...
// 检查特定类型的副作用,您可以这样做:
if (effect is MyEffect) {
// 对MyEffect做些事情
}
},
child: const SomeWidget(),
);
更多关于Flutter可控制组件插件controllable_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
controllable_flutter
是一个用于在 Flutter 中创建可控制组件的插件。它允许你通过外部控制器来管理组件的状态和行为,从而实现更灵活和可复用的 UI 组件。
安装
首先,你需要在 pubspec.yaml
文件中添加 controllable_flutter
依赖:
dependencies:
flutter:
sdk: flutter
controllable_flutter: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
基本用法
controllable_flutter
的核心思想是通过 Controller
来管理组件的状态。你可以通过继承 Controller
类来创建自定义的控制器,并将其与组件绑定。
1. 创建控制器
首先,创建一个控制器类,继承自 Controller
:
import 'package:controllable_flutter/controllable_flutter.dart';
class MyController extends Controller {
int _counter = 0;
int get counter => _counter;
void increment() {
_counter++;
notifyListeners(); // 通知监听器状态已更新
}
}
2. 创建可控制组件
接下来,创建一个可控制组件,使用 ControllableWidget
来绑定控制器:
import 'package:flutter/material.dart';
import 'package:controllable_flutter/controllable_flutter.dart';
class MyWidget extends ControllableWidget<MyController> {
MyWidget({Key? key}) : super(key: key, controller: MyController());
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Controllable Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter:',
),
Text(
'${controller.counter}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
3. 使用可控制组件
最后,在你的应用中使用这个可控制组件:
import 'package:flutter/material.dart';
import 'my_widget.dart'; // 导入你创建的可控制组件
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Controllable Flutter Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyWidget(), // 使用可控制组件
);
}
}
高级用法
1. 多个控制器
你可以为同一个组件绑定多个控制器,以实现更复杂的状态管理。
class MyWidget extends ControllableWidget<MyController> {
MyWidget({Key? key}) : super(key: key, controller: MyController());
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Controllable Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter:',
),
Text(
'${controller.counter}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
2. 监听控制器状态
你可以通过 addListener
方法来监听控制器状态的变化,并在状态变化时执行相应的操作。
class MyWidget extends ControllableWidget<MyController> {
MyWidget({Key? key}) : super(key: key, controller: MyController());
[@override](/user/override)
void initState() {
super.initState();
controller.addListener(_onControllerChange);
}
void _onControllerChange() {
// 当控制器状态变化时执行的操作
print('Counter changed: ${controller.counter}');
}
[@override](/user/override)
void dispose() {
controller.removeListener(_onControllerChange);
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Controllable Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Counter:',
),
Text(
'${controller.counter}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}