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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:06:22