为什么这个 BlocBuilder 在第二次触发后不重建我的列表?
Why this BlocBuilder do not rebuild my list after second trigger?
我有 cubit,我可以在其中下载电影并将其传递给列表:
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));
}
}
}
}
我在 BlocBuilder 中这样调用它:
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();
}
}),
我正在通过按下按钮触发 cubit 函数 fetchMovies:
IconButton(
icon: const Icon(Icons.search),
onPressed: () async {
await context.read<MovieSearchCubit>().fetchMovies(inputStr);
},
),
但是列表只是第一次构建,数据收集正确,问题在于显示。感谢您的任何提示。
稍后添加:这里看起来像 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 新状态仅在 oldState != newState
时发出,这意味着我们需要一种方法来正确区分状态的两个实例,我们这里有两种方法,或者通过覆盖状态的等号运算符,或者像您的情况一样,我们可以使用 Equatable
来轻松检查是否相等。
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
}
但是您的 class 缺少道具,因此 MovieState 的任何实例都是相等的!并且状态只会发出一次,这里的简单解决方法是将 属性 添加到您的道具方法中,以便进行适当的检查
@override
List<Object?> get props => [status, movies];
我有 cubit,我可以在其中下载电影并将其传递给列表:
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));
}
}
}
}
我在 BlocBuilder 中这样调用它:
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();
}
}),
我正在通过按下按钮触发 cubit 函数 fetchMovies:
IconButton(
icon: const Icon(Icons.search),
onPressed: () async {
await context.read<MovieSearchCubit>().fetchMovies(inputStr);
},
),
但是列表只是第一次构建,数据收集正确,问题在于显示。感谢您的任何提示。
稍后添加:这里看起来像 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 新状态仅在 oldState != newState
时发出,这意味着我们需要一种方法来正确区分状态的两个实例,我们这里有两种方法,或者通过覆盖状态的等号运算符,或者像您的情况一样,我们可以使用 Equatable
来轻松检查是否相等。
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
}
但是您的 class 缺少道具,因此 MovieState 的任何实例都是相等的!并且状态只会发出一次,这里的简单解决方法是将 属性 添加到您的道具方法中,以便进行适当的检查
@override
List<Object?> get props => [status, movies];