I have cubit in which I download movies and pass it to the list:
class MovieSearchCubit extends Cubit<MovieState> {
MovieSearchRepoInterface movieSearchRepository;
List<Movie> emptyList = [];
MovieSearchCubit({required this.movieSearchRepository})
: super(const MovieState());
Future<void> fetchMovies(String movieName) async {
if (state.status != MovieStatus.failure) {
final movies = await movieSearchRepository.searchMovies(movieName);
if (movies.isRight()) {
emit(state.copyWith(
status: MovieStatus.success,
posts: List.of(state.movies)
..addAll(
movies.getOrElse((l) => emptyList),
)));
} else {
emit(state.copyWith(status: MovieStatus.failure));
}
}
}
}
and I'm calling it in BlocBuilder like this:
BlocBuilder<MovieSearchCubit, MovieState>(
builder: (context, state) {
switch (state.status) {
case MovieStatus.failure:
return const Center(child: Text('failed to fetch posts'));
case MovieStatus.success:
if (state.movies.isEmpty) {
return const Center(child: Text('no posts'));
}
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return index >= state.movies.length
? BottomLoader()
: MovieCard(
});
},
itemCount: state.movies.length,
),
);
default:
return Container();
}
}),
I'm triggering cubit function fetchMovies by pressing button:
IconButton(
icon: const Icon(Icons.search),
onPressed: () async {
await context.read<MovieSearchCubit>().fetchMovies(inputStr);
},
),
But the list is build only the first time, data is gathered correctly, the problem is with displaying it. Thanks for any tips.
Added later: Here how looks like MovieState
class MovieState extends Equatable {
const MovieState({
this.status = MovieStatus.initial,
this.movies = const <Movie>[],
});
final MovieStatus status;
final List<Movie> movies;
MovieState copyWith({
MovieStatus? status,
List<Movie>? posts,
}) {
return MovieState(
status: status ?? this.status,
movies: posts ?? this.movies,
);
}
@override
List<Object?> get props => [];
}
BLoC new state is only emitted when oldState != newState
this means that we need a way to correctly differentiate between two instances of the state, we have two ways here, or by overriding the equals operator of your state, or like in your case we may use Equatable
to have an easy way to check for equality.
class MovieState extends Equatable {
const MovieState({
this.status = MovieStatus.initial,
this.movies = const <Movie>[],
});
final MovieStatus status;
final List<Movie> movies;
MovieState copyWith({
MovieStatus? status,
List<Movie>? posts,
}) {
return MovieState(
status: status ?? this.status,
movies: posts ?? this.movies,
);
}
@override
List<Object?> get props => []; <--- Missing props
}
Your class however is missing the props, so any instance of MovieState will be equal! and the state will be emitted only once, the easy fix here is to add the property to your props methods in order to have a proper check
@override
List<Object?> get props => [status, movies];