Reputation: 2420
I get a _CastError
error at the last line of this piece of code
BlocBuilder buildUsernameField() {
return BlocBuilder<ProfileBloc, ProfileState>(
buildWhen: (previous, current) => previous != current && current is EditingUserInfo,
builder: (context, state) => TextField(
keyboardType: TextInputType.name,
controller: TextEditingController(
text: (state as EditingUserInfo).username.value),
saying that
I/flutter (26787): The following _CastError was thrown building BlocBuilder<ProfileBloc, ProfileState>(dirty, state:
I/flutter (26787): _BlocBuilderBaseState<ProfileBloc, ProfileState>#25b87):
I/flutter (26787): type 'Success' is not a subtype of type 'EditingUserInfo' in type cast
So what's happening is that it tries to build that widget when I am in another state (success). But in the buildWhen
parameter, I specified that the widget should only build when the state is EditingUserInfo
.
So as far as I understand, this error should not happen.
Here's my ProfileState
:
part of 'profile_bloc.dart';
abstract class ProfileState extends Equatable {
const ProfileState();
@override
List<Object> get props => [];
}
class ProfileInitial extends ProfileState {}
class EditingUserInfo extends ProfileState {
final Username username;
final Bio bio;
final PhotoUrl photoUrl;
final City city;
final FormzStatus status;
const EditingUserInfo({
this.username = const Username.pure(),
this.bio = const Bio.pure(),
this.photoUrl = const PhotoUrl.pure(),
this.city = const City.pure(),
this.status = FormzStatus.pure,
});
EditingUserInfo copyWith({Username username, Bio bio, PhotoUrl photoUrl, City city, FormzStatus status}){
return EditingUserInfo(
username: username ?? this.username,
bio: bio ?? this.bio,
photoUrl: photoUrl ?? this.photoUrl,
city: city ?? this.city,
status: status ?? this.status,
);
}
@override
List<Object> get props => [username, bio, photoUrl, city];
}
class Loading extends ProfileState {}
class Error extends ProfileState {
final String message;
const Error({this.message});
@override
List<Object> get props => [message];
}
class Success extends ProfileState {
final String message;
const Success({this.message});
@override
List<Object> get props => [message];
}
Upvotes: 8
Views: 16677
Reputation: 650
The buildWhen
condition is not considered the first time the widget is built. It's purpose is to avoid all succesive builts.
In your case, inside builder
you could add the following condition to solve the problem:
builder: (context, state) {
if (state is! EditingUserInfo) {
return Container();
}
return TextField(
keyboardType: TextInputType.name,
controller: TextEditingController(
text: (state as EditingUserInfo).username.value),
Upvotes: 0
Reputation: 144
Here's a clear answer to your questioning user54517 :
buildWhen
will prevent your widget to rebuild if the bloc state changes, but it will not prevent it if the framework rebuilds it for any other reason (for instance, if one of its parents need a rebuild...).
That's why you still need to check the state in the builder method.
Source: https://github.com/felangel/bloc/issues/1413#issuecomment-655568783
Upvotes: 1
Reputation: 671
You still have to check that the state variable is the proper state. The state is checked EVERY time it is changed, so the state variable can still be a different state, it just doesn't rebuild unless the buildWhen conditions are true.
BlocBuilder buildUsernameField() {
return BlocBuilder<ProfileBloc, ProfileState>(
buildWhen: (previous, current) => previous != current && current is EditingUserInfo,
builder: (context, state) {
if(state is EditingUserInfo) {
return TextField(
keyboardType: TextInputType.name,
controller: TextEditingController(
text: state.username.info)
}
}
Upvotes: 9