Flutter Bloc状态异常:FetchLoadingState无法转为FetchDataState
解决HydratedBloc状态类型不匹配异常
问题根源
你的FetchBloc类定义时,泛型状态指定为FetchDataState,但在_fetchWeather方法里emit了FetchLoadingState——这两个状态没有继承关系,属于不同类型,所以触发了type 'FetchLoadingState' is not a subtype of type 'FetchDataState'的类型转换异常。
解决步骤
- 定义统一的基础状态类
让所有相关状态都继承同一个抽象类,这样Bloc的泛型就能兼容所有状态:
// 基础状态抽象类 abstract class FetchState {} // 原有的数据状态,继承基础状态 class FetchDataState extends FetchState { FetchDataState({ required this.fetchedData, required this.cityNames, this.snackBar = false, required this.date, }); final List fetchedData; final List cityNames; final bool snackBar; final DateTime date; // HydratedBloc需要的序列化方法 factory FetchDataState.fromJson(Map<String, dynamic> json) { return FetchDataState( fetchedData: json['fetchedData'] as List, cityNames: json['cityNames'] as List, snackBar: json['snackBar'] as bool, date: DateTime.parse(json['date'] as String), ); } Map<String, dynamic> toJson() { return { 'fetchedData': fetchedData, 'cityNames': cityNames, 'snackBar': snackBar, 'date': date.toIso8601String(), }; } } // 加载状态,同样继承基础状态 class FetchLoadingState extends FetchState {}
- 修改Bloc的泛型定义
把Bloc的状态泛型从FetchDataState改成基础的FetchState,同时确保Emitter的类型也对应:
class FetchBloc extends HydratedBloc<FetchEvent, FetchState> { FetchBloc() : super(FetchDataState(fetchedData: const [], cityNames: const [], date: DateTime.now())) { on<FetchWeather>(_fetchWeather); on<FetchCurrentLocation>(_fetchCurrentLocationWeather); on<RefreshData>(_refreshData); on<DeleteData>(_deleteData); } // Emitter类型改为Emitter<FetchState> void _fetchWeather(FetchWeather event, Emitter<FetchState> emit) async { emit(FetchLoadingState()); event = await getCurrentWeather(event.cityName); if (event.data!.city == "city not found") { // 访问state字段时,需要先转换为FetchDataState类型 final currentDataState = state as FetchDataState; emit( FetchDataState( cityNames: List.from(currentDataState.cityNames), fetchedData: List.from(currentDataState.fetchedData), snackBar: true, date: DateTime.now(), ), ); } else { // 处理正常获取数据的逻辑,emit更新后的FetchDataState final currentDataState = state as FetchDataState; emit( FetchDataState( cityNames: [...currentDataState.cityNames, event.data!.city], fetchedData: [...currentDataState.fetchedData, event.data!], snackBar: false, date: DateTime.now(), ), ); } } // 处理HydratedBloc的序列化,只持久化FetchDataState @override FetchState? fromJson(Map<String, dynamic> json) { return FetchDataState.fromJson(json); } @override Map<String, dynamic>? toJson(FetchState state) { if (state is FetchDataState) { return state.toJson(); } // 加载状态不需要持久化,返回null return null; } }
- 额外注意事项
- 当需要访问
state中的具体字段(比如cityNames)时,必须先将state转换为FetchDataState类型,因为现在state的类型是抽象的FetchState。 - HydratedBloc的序列化方法中,只对
FetchDataState进行持久化,加载状态不需要保存,所以在toJson里做类型判断,非数据状态返回null。
内容的提问来源于stack exchange,提问作者Shashank Jain
相关产品推荐
相关产品推荐

