You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通知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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 04:13:24