Flutter中如何通过Bloc实现从Budget对象取款并返回更新对象
你的思路方向是对的,但不用把Budget对象传入Withdraw事件——Bloc可以从当前状态或者仓库获取最新的Budget实例,这样更符合Bloc的状态管理逻辑。下面是具体的实现步骤和修改代码:
1. 优化Withdraw事件定义
只需要传递取款金额即可,无需传入Budget对象:
part of 'budget_bloc.dart'; abstract class BudgetEvent extends Equatable { const BudgetEvent(); @override List<Object> get props => []; } class AppStarted extends BudgetEvent {} class Withdraw extends BudgetEvent { final double amount; const Withdraw(this.amount); @override List<Object> get props => [amount]; }
2. 在BudgetBloc中处理Withdraw事件
从当前状态获取最新的Budget,执行取款操作后更新仓库并发射新状态:
import 'package:bloc/bloc.dart'; import 'package:budget_app/model/budget.dart'; import 'package:budget_app/model/budget_repository.dart'; import 'package:equatable/equatable.dart'; part 'budget_event.dart'; part 'budget_state.dart'; class BudgetBloc extends Bloc<BudgetEvent, BudgetState> { final BudgetRepository budgetRepository; BudgetBloc({required this.budgetRepository}) : super(BudgetInitial()) { on<AppStarted>((event, emit) async { emit(BudgetLoading()); if (await budgetRepository.hasBudget()) { var budget = await budgetRepository.getBudget(); emit(BudgetLoaded(budget: budget)); } else { emit(BudgetNew()); } }); on<Withdraw>((event, emit) async { if (state is BudgetLoaded) { emit(BudgetLoading()); try { final currentBudget = (state as BudgetLoaded).budget; // 执行取款操作(假设withdraw返回更新后的Budget实例) final updatedBudget = currentBudget.withdraw(event.amount); // 持久化更新后的预算 await budgetRepository.saveBudget(updatedBudget); // 发射携带新预算的状态 emit(BudgetLoaded(budget: updatedBudget)); } catch (e) { // 处理余额不足等异常情况 emit(BudgetError(message: e.toString())); // 切回之前的有效状态,避免停留在加载态 emit(BudgetLoaded(budget: (state as BudgetLoaded).budget)); } } }); } }
3. 完善BudgetState的Equatable实现
确保所有状态类正确实现props,否则Bloc无法识别状态变化:
part of 'budget_bloc.dart'; abstract class BudgetState extends Equatable { const BudgetState(); @override List<Object> get props => []; } class BudgetInitial extends BudgetState {} class BudgetLoading extends BudgetState {} class BudgetNew extends BudgetState {} class BudgetLoaded extends BudgetState { final Budget budget; const BudgetLoaded({required this.budget}); @override List<Object> get props => [budget]; } // 新增错误状态,处理取款异常 class BudgetError extends BudgetState { final String message; const BudgetError({required this.message}); @override List<Object> get props => [message]; }
4. 确保Budget类的withdraw方法正确实现
推荐使用不可变对象设计,withdraw返回新的Budget实例:
class Budget extends Equatable { final String name; final double value; const Budget({required this.name, required this.value}); Budget withdraw(double amount) { if (amount > value) { throw Exception('余额不足,无法完成取款'); } return Budget(name: name, value: value - amount); } @override List<Object> get props => [name, value]; }
核心逻辑说明
- 不需要在
Withdraw事件中传递Budget:Bloc的state已经持有最新的预算实例,直接从状态获取更可靠,避免传递过时对象。 - 取款后必须更新仓库:保证数据持久化,下次启动App能读取到最新的预算状态。
- 异常处理:避免因余额不足等情况导致App崩溃,同时及时恢复到有效状态。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

