Flutter Cubit状态未正确emit:多店铺购物车计数仅首次生效
多店铺购物车Cubit的emit仅首次生效问题
我开发了一个带多店铺购物车的计数器应用,用户点击增量按钮时应触发状态更新,但仅首次操作生效——只有首个店铺的商品能添加到对应Map里。预期每个店铺拥有独立购物车,用户进入店铺点击按钮时,通过context.read<CounterCubit>().increment(...)更新状态:如果店铺名称对应的Map不存在就创建,同时添加/更新商品的价格与计数(包含价格和计数两个嵌套Map)。
状态类代码
class CounterState extends Equatable { Map<int?, String?> storeNameperId; Map<String, Map<String, String>> storeNamePriceperProduct; Map<String, Map<String, int>> storeNameCounterperProduct; int? storeId; String? storeName; CounterState({ this.storeId, this.storeName, required this.storeNameperId, required this.storeNamePriceperProduct, required this.storeNameCounterperProduct, }); @override List<Object?> get props => [ storeId, storeName, storeNameperId, storeNamePriceperProduct, storeNameCounterperProduct, ]; } class CounterDecrementedState extends CounterState { CounterDecrementedState({ super.storeId, super.storeName, required super.storeNameperId, required super.storeNamePriceperProduct, required super.storeNameCounterperProduct, }); @override List<Object?> get props => [storeId, storeName]; } class CounterInitialState extends CounterState { CounterInitialState({ super.storeId, super.storeName, required super.storeNameperId, required super.storeNamePriceperProduct, required super.storeNameCounterperProduct, }); @override List<Object?> get props => [storeId, storeName]; } class CounterIncrementedState extends CounterState { CounterIncrementedState({ super.storeId, super.storeName, required super.storeNameperId, required super.storeNamePriceperProduct, required super.storeNameCounterperProduct, }); @override List<Object?> get props => [storeId, storeName]; }
Cubit类代码(增量逻辑)
class CounterCubit extends Cubit<CounterState> { CounterCubit() : super( CounterInitialState( storeId: 0, storeName: '', storeNameperId: {}, storeNamePriceperProduct: {}, storeNameCounterperProduct: {}, ), ); void increment( String productId, String price, int inputedId, String storeName, ) { final prevPriceMap = state.storeNamePriceperProduct[storeName]; final prevCounterMap = state.storeNameCounterperProduct[storeName]; final newPriceMap = prevPriceMap != null ? Map<String, String>.from(prevPriceMap) : <String, String>{}; final newCounterMap = prevCounterMap != null ? Map<String, int>.from(prevCounterMap) : <String, int>{}; newPriceMap[productId] = newPriceMap[productId] ?? price; newCounterMap[productId] = (newCounterMap[productId] ?? 0) + 1; final updatedStoreNameperPriceperProduct = Map<String, Map<String, String>>.from(state.storeNamePriceperProduct); final updatedStoreNamepercounterperProduct = Map<String, Map<String, int>>.from(state.storeNameCounterperProduct); updatedStoreNameperPriceperProduct[storeName] = newPriceMap; updatedStoreNamepercounterperProduct[storeName] = newCounterMap; emit( CounterIncrementedState( storeNameperId: {...state.storeNameperId, inputedId: storeName}, storeNamePriceperProduct: updatedStoreNameperPriceperProduct, storeNameCounterperProduct: updatedStoreNamepercounterperProduct, storeId: state.storeId, ), ); } }
问题根源
- 子类
props重写错误:所有状态子类(CounterIncrementedState等)都只将storeId和storeName纳入props对比,但父类CounterState的props包含了购物车核心数据(价格、计数Map)。Cubit通过对比props判断状态是否变化,后续操作若storeId/storeName未变,即使购物车Map已更新,Cubit会判定状态无变化,不触发UI刷新。 - emit参数缺失:触发
CounterIncrementedState时未传递storeName,可能导致状态内该字段值异常。
修复方案
1. 修正状态子类的props实现
删除所有子类的props重写,直接继承父类CounterState的props,确保所有核心状态数据都参与变化判断:
class CounterState extends Equatable { Map<int?, String?> storeNameperId; Map<String, Map<String, String>> storeNamePriceperProduct; Map<String, Map<String, int>> storeNameCounterperProduct; int? storeId; String? storeName; CounterState({ this.storeId, this.storeName, required this.storeNameperId, required this.storeNamePriceperProduct, required this.storeNameCounterperProduct, }); @override List<Object?> get props => [ storeId, storeName, storeNameperId, storeNamePriceperProduct, storeNameCounterperProduct, ]; } // 子类不再重写props class CounterDecrementedState extends CounterState { CounterDecrementedState({ super.storeId, super.storeName, required super.storeNameperId, required super.storeNamePriceperProduct, required super.storeNameCounterperProduct, }); } class CounterInitialState extends CounterState { CounterInitialState({ super.storeId, super.storeName, required super.storeNameperId, required super.storeNamePriceperProduct, required super.storeNameCounterperProduct, }); } class CounterIncrementedState extends CounterState { CounterIncrementedState({ super.storeId, super.storeName, required super.storeNameperId, required super.storeNamePriceperProduct, required super.storeNameCounterperProduct, }); }
2. 补充emit时的参数
确保CounterIncrementedState的storeName和storeId参数正确传递:
void increment( String productId, String price, int inputedId, String storeName, ) { final prevPriceMap = state.storeNamePriceperProduct[storeName]; final prevCounterMap = state.storeNameCounterperProduct[storeName]; final newPriceMap = prevPriceMap != null ? Map<String, String>.from(prevPriceMap) : <String, String>{}; final newCounterMap = prevCounterMap != null ? Map<String, int>.from(prevCounterMap) : <String, int>{}; newPriceMap[productId] = newPriceMap[productId] ?? price; newCounterMap[productId] = (newCounterMap[productId] ?? 0) + 1; final updatedStoreNameperPriceperProduct = Map<String, Map<String, String>>.from(state.storeNamePriceperProduct); final updatedStoreNamepercounterperProduct = Map<String, Map<String, int>>.from(state.storeNameCounterperProduct); updatedStoreNameperPriceperProduct[storeName] = newPriceMap; updatedStoreNamepercounterperProduct[storeName] = newCounterMap; emit( CounterIncrementedState( storeNameperId: {...state.storeNameperId, inputedId: storeName}, storeNamePriceperProduct: updatedStoreNameperPriceperProduct, storeNameCounterperProduct: updatedStoreNamepercounterperProduct, storeId: inputedId, // 根据业务需求传递当前店铺ID,或保留state.storeId storeName: storeName, // 补充传递店铺名称 ), ); }
内容的提问来源于stack exchange,提问作者Abdlrhman Bashir
相关产品推荐
相关产品推荐

