GetX State Management Patterns by kaakati/rails-enterprise-dev
npx skills add https://github.com/kaakati/rails-enterprise-dev --skill 'GetX State Management Patterns'class UserController extends GetxController {
// 简单的响应式变量
final count = 0.obs;
// 复杂的响应式变量
final user = Rx<User?>(null);
// 响应式列表
final users = <User>[].obs;
// 响应式映射
final settings = <String, dynamic>{}.obs;
// Getter(推荐使用)
int get countValue => count.value;
User? get currentUser => user.value;
}
// 选项 1: Obx(轻量级)
Obx(() => Text(controller.count.toString()))
// 选项 2: GetX(配合依赖注入)
GetX<UserController>(
builder: (controller) => Text(controller.user?.name ?? '加载中...'),
)
// 选项 3: GetBuilder(无需响应式变量)
GetBuilder<UserController>(
builder: (controller) => Text(controller.userName),
)
// 立即创建实例
Get.put(UserController());
// 懒加载实例(首次使用时创建)
Get.lazyPut(() => UserController());
// 单例模式(在路由间持久化)
Get.putAsync(() => StorageService().init());
// Fenix 模式(当再次访问路由时重新创建)
Get.lazyPut(() => UserController(), fenix: true);
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
class UserBinding extends Bindings {
@override
void dependencies() {
// 数据源
Get.lazyPut(() => UserProvider(Get.find()));
Get.lazyPut(() => UserLocalSource(Get.find()));
// 仓库
Get.lazyPut<UserRepository>(
() => UserRepositoryImpl(Get.find(), Get.find()),
);
// 用例
Get.lazyPut(() => GetUser(Get.find()));
// 控制器
Get.lazyPut(() => UserController(getUserUseCase: Get.find()));
}
}
// 导航到路由
Get.to(() => ProfilePage());
// 通过名称导航
Get.toNamed('/profile');
// 导航并移除前一个页面
Get.off(() => LoginPage());
// 导航并移除所有之前的页面
Get.offAll(() => HomePage());
// 返回
Get.back();
// 返回并携带结果
Get.back(result: user);
// 发送参数
Get.toNamed('/profile', arguments: {'id': '123'});
// 接收参数
final args = Get.arguments as Map<String, dynamic>;
final id = args['id'];
class AppRoutes {
static const initial = '/splash';
static final routes = [
GetPage(
name: '/splash',
page: () => SplashPage(),
binding: SplashBinding(),
),
GetPage(
name: '/login',
page: () => LoginPage(),
binding: AuthBinding(),
transition: Transition.fadeIn,
),
GetPage(
name: '/home',
page: () => HomePage(),
binding: HomeBinding(),
middlewares: [AuthMiddleware()],
),
];
}
class UserController extends GetxController {
@override
void onInit() {
super.onInit();
// 在控制器分配后立即调用
loadUser();
}
@override
void onReady() {
super.onReady();
// 在组件渲染后调用
analytics.logScreenView();
}
@override
void onClose() {
// 清理资源
_subscription.cancel();
super.onClose();
}
}
// Snackbar
Get.snackbar(
'成功',
'用户创建成功',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green,
);
// 对话框
Get.dialog(
AlertDialog(
title: Text('确认'),
content: Text('确定吗?'),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text('取消'),
),
TextButton(
onPressed: () {
deleteUser();
Get.back();
},
child: Text('删除'),
),
],
),
);
// 底部弹窗
Get.bottomSheet(
Container(
child: Column(
children: [
ListTile(
title: Text('选项 1'),
onTap: () => Get.back(result: 1),
),
],
),
),
);
onClose() 中清理资源UserController,而不是 Controller1)// ❌ 错误做法:业务逻辑放在控制器中
class UserController extends GetxController {
Future<void> createUser(String name, String email) async {
// 在控制器中直接进行 API 调用
final response = await http.post(...);
// 业务逻辑放在控制器中
if (response.statusCode == 201) {
user.value = User.fromJson(response.body);
}
}
}
// ✅ 正确做法:委托给用例处理
class UserController extends GetxController {
final CreateUser createUserUseCase;
Future<void> createUser(String name, String email) async {
final result = await createUserUseCase(name, email);
result.fold(
(failure) => _handleError(failure),
(user) => user.value = user,
);
}
}
每周安装量
–
代码仓库
GitHub 星标数
7
首次出现
–
安全审计
class UserController extends GetxController {
// Simple reactive variable
final count = 0.obs;
// Complex reactive variable
final user = Rx<User?>(null);
// Reactive list
final users = <User>[].obs;
// Reactive map
final settings = <String, dynamic>{}.obs;
// Getters (recommended)
int get countValue => count.value;
User? get currentUser => user.value;
}
// Option 1: Obx (lightweight)
Obx(() => Text(controller.count.toString()))
// Option 2: GetX (with dependency injection)
GetX<UserController>(
builder: (controller) => Text(controller.user?.name ?? 'Loading...'),
)
// Option 3: GetBuilder (no reactive variables needed)
GetBuilder<UserController>(
builder: (controller) => Text(controller.userName),
)
// Immediate instance
Get.put(UserController());
// Lazy instance (created when first used)
Get.lazyPut(() => UserController());
// Singleton (persists across routes)
Get.putAsync(() => StorageService().init());
// Fenix (recreates when route is accessed again)
Get.lazyPut(() => UserController(), fenix: true);
class UserBinding extends Bindings {
@override
void dependencies() {
// Data sources
Get.lazyPut(() => UserProvider(Get.find()));
Get.lazyPut(() => UserLocalSource(Get.find()));
// Repository
Get.lazyPut<UserRepository>(
() => UserRepositoryImpl(Get.find(), Get.find()),
);
// Use cases
Get.lazyPut(() => GetUser(Get.find()));
// Controller
Get.lazyPut(() => UserController(getUserUseCase: Get.find()));
}
}
// Navigate to route
Get.to(() => ProfilePage());
// Navigate with name
Get.toNamed('/profile');
// Navigate and remove previous
Get.off(() => LoginPage());
// Navigate and remove all previous
Get.offAll(() => HomePage());
// Go back
Get.back();
// Go back with result
Get.back(result: user);
// Send arguments
Get.toNamed('/profile', arguments: {'id': '123'});
// Receive arguments
final args = Get.arguments as Map<String, dynamic>;
final id = args['id'];
class AppRoutes {
static const initial = '/splash';
static final routes = [
GetPage(
name: '/splash',
page: () => SplashPage(),
binding: SplashBinding(),
),
GetPage(
name: '/login',
page: () => LoginPage(),
binding: AuthBinding(),
transition: Transition.fadeIn,
),
GetPage(
name: '/home',
page: () => HomePage(),
binding: HomeBinding(),
middlewares: [AuthMiddleware()],
),
];
}
class UserController extends GetxController {
@override
void onInit() {
super.onInit();
// Called immediately after controller is allocated
loadUser();
}
@override
void onReady() {
super.onReady();
// Called after widget is rendered
analytics.logScreenView();
}
@override
void onClose() {
// Clean up resources
_subscription.cancel();
super.onClose();
}
}
// Snackbar
Get.snackbar(
'Success',
'User created successfully',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: Colors.green,
);
// Dialog
Get.dialog(
AlertDialog(
title: Text('Confirm'),
content: Text('Are you sure?'),
actions: [
TextButton(
onPressed: () => Get.back(),
child: Text('Cancel'),
),
TextButton(
onPressed: () {
deleteUser();
Get.back();
},
child: Text('Delete'),
),
],
),
);
// Bottom sheet
Get.bottomSheet(
Container(
child: Column(
children: [
ListTile(
title: Text('Option 1'),
onTap: () => Get.back(result: 1),
),
],
),
),
);
onClose()UserController, not Controller1)// ❌ BAD: Business logic in controller
class UserController extends GetxController {
Future<void> createUser(String name, String email) async {
// Direct API call in controller
final response = await http.post(...);
// Business logic in controller
if (response.statusCode == 201) {
user.value = User.fromJson(response.body);
}
}
}
// ✅ GOOD: Delegate to use case
class UserController extends GetxController {
final CreateUser createUserUseCase;
Future<void> createUser(String name, String email) async {
final result = await createUserUseCase(name, email);
result.fold(
(failure) => _handleError(failure),
(user) => user.value = user,
);
}
}
Weekly Installs
–
Repository
GitHub Stars
7
First Seen
–
Security Audits
Flutter无障碍功能实现指南:UI设计、语义组件与网页适配完整教程
3,000 周安装