Consider these states:
class ExerciseInitialState extends ExerciseState {}
class ExerciseLoadingState extends ExerciseState {}
class ExerciseLoadedState extends ExerciseState {
final List<Data> data;
const ExerciseLoadedState({required this.data});
@override
List<Object> get props => [data];
// total count
int get totalCount => data.length;
}
In the UI, I have to cast the state (ExerciseState
) to ExerciseLoadedState
to be able to access its property which doesn't exist in the ExerciseLoadingState
and ExerciseInitialState
:
final total = (context.read<ExerciseBloc>().state as ExerciseLoadedState).totalCount
It looks awkward to me to have to do this casting all the time. Is the only solution to add the same properties to the base class ExerciseState
?
CodePudding user response:
It should not feel wrong to you - if you want the property to be available in all the state classes, it should be defined in the base class. E.g. you cannot get the totalCount
while the state is ExerciseLoadingState
simply because this property is not defined here - you need to promote the type to a specific one.
There are two possible solutions to this problem:
- Promote the type to
ExerciseLoadedState
to access the property:
return BlocBuilder<ExerciseBloc, ExerciseState>(
builder: (context, state) {
final totalCount = state is ExerciseLoadedState
? (state as ExerciseLoadedState).totalCount
: 0;
},
);
- Create an extension method on
ExerciseState
:
extension ExerciseStateX on ExerciseState {
int get totalCount => this is ExerciseLoadedState
? (this as ExerciseLoadedState).totalCount
: 0;
}
With the extension, you won't need to do the type promotion in your UI layer.