如何通知Widget类显示Snackbar?(无第三方状态管理库)
解决方案:无第三方状态管理下实现Snackbar通知
下面提供三种无需依赖Riverpod、Bloc等第三方包的实现方式,可根据场景选择:
方法1:使用回调函数(最简单直接)
直接给createCategory方法添加成功/失败回调参数,UI层调用时传入Snackbar显示逻辑:
修改CategoriesController的createCategory方法
void createCategory(String categoryName, { required void Function(String) onSuccess, required void Function(String) onFailure, }) { createCategoryUseCase.createCategory(categoryName).fold( (failure) { onFailure(failure.message); }, (id) { debugPrint('Category created with id: $id'); onSuccess('分类创建成功,ID:$id'); }, ); }
修改UI层调用逻辑
在HomeView的AlertDialog确认按钮中传入回调:
TextButton( onPressed: () { final categoryName = textController.text.trim(); if (categoryName.isEmpty) { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请输入分类名称')), ); return; } controller.createCategory( categoryName, onSuccess: (message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message)), ); }, onFailure: (errorMessage) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('创建失败:$errorMessage'), backgroundColor: Colors.red), ); }, ); Navigator.pop(context); textController.clear(); }, child: const Text('Add'), )
方法2:新增操作状态Stream(适合多处监听场景)
在CategoriesController中新增StreamController,专门发送创建操作的状态消息,UI层监听该Stream实现通知:
修改CategoriesController
class CategoriesController { final _todoStreamController = StreamController<List<CategoryModel>>(); // 新增:发送操作状态的广播StreamController final _actionStatusController = StreamController<String>.broadcast(); Stream<List<CategoryModel>> get categoryStream => _todoStreamController.stream; // 暴露状态Stream给UI层 Stream<String> get actionStatusStream => _actionStatusController.stream; // ... 原有代码不变 ... void createCategory(String categoryName) { createCategoryUseCase.createCategory(categoryName).fold( (failure) { _actionStatusController.addError(failure.message); }, (id) { debugPrint('Category created with id: $id'); _actionStatusController.add('分类创建成功,ID:$id'); }, ); } @override void dispose() { _todoStreamController.close(); _actionStatusController.close(); // 新增关闭逻辑 super.dispose(); } }
在UI层监听状态Stream
在HomeView的State中初始化监听:
class _HomeViewState extends State<HomeView> { final textController = TextEditingController(); StreamSubscription? _statusSubscription; @override void initState() { super.initState(); final controller = CategoriesControllerProvider.of(context).categoriesController; // 监听操作状态 _statusSubscription = controller.actionStatusStream.listen( (message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message)), ); }, onError: (error) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('创建失败:$error'), backgroundColor: Colors.red), ); }, ); } @override void dispose() { textController.dispose(); _statusSubscription?.cancel(); // 取消订阅 CategoriesControllerProvider.of(context).categoriesController.dispose(); super.dispose(); } // ... 原有build方法不变,调用createCategory时无需传回调 ... }
方法3:让createCategory返回Future(适合异步等待场景)
修改createCategory方法返回Future,UI层通过async/await直接处理结果:
修改CategoriesController的createCategory方法
Future<Either<Failure, String>> createCategory(String categoryName) { return Future.value(createCategoryUseCase.createCategory(categoryName)); }
修改UI层调用逻辑
TextButton( onPressed: () async { final categoryName = textController.text.trim(); if (categoryName.isEmpty) { Navigator.pop(context); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('请输入分类名称')), ); return; } final result = await controller.createCategory(categoryName); Navigator.pop(context); textController.clear(); result.fold( (failure) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('创建失败:${failure.message}'), backgroundColor: Colors.red), ); }, (id) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('分类创建成功,ID:$id')), ); }, ); }, child: const Text('Add'), )
内容的提问来源于stack exchange,提问作者Inan Mahmud
相关产品推荐
相关产品推荐

