You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flutter Bloc搜索功能异常:搜索结果仅显示1条数据且存在问题

问题排查与修复方案

我帮你梳理了代码里的几个关键问题,这些应该就是导致搜索结果只显示1条和异常的核心原因:

1. Bloc事件处理逻辑冲突且存在错误

你在SearchNewsBloc里同时混用了Bloc 8.0+的新on<Event>绑定方式旧版的mapEventToState方法,这会导致事件被重复处理;而且on<SearchNewsEvent>里的逻辑完全错误:

  • 错误地判断event is SearchNewsLoadingState(这是状态类,不是事件类)
  • 处理完事件后又主动add(StartSearchNewsEvent),直接引发无限循环触发事件,数据被反复覆盖

修复方法:删除冗余的on<SearchNewsEvent>代码块,改用标准的on绑定逻辑(推荐),或者只保留mapEventToState。以下是标准的on绑定写法:

class SearchNewsBloc extends Bloc<SearchNewsEvent, SearchNewsState> {
  final NewsRepository newsRepository;

  SearchNewsBloc({required this.newsRepository}) : super(SearchNewsInitial()) {
    on<StartSearchNewsEvent>(_mapStartSearchToState);
  }

  Future<void> _mapStartSearchToState(
    StartSearchNewsEvent event,
    Emitter<SearchNewsState> emit,
  ) async {
    try {
      emit(SearchNewsLoadingState());
      final articlesList = await newsRepository.searchNews(event.query);
      emit(SearchNewsLoadedState(articleList: articlesList));
    } catch (e) {
      emit(SearchNewsErrorState(errorMessage: e.toString()));
    }
  }
}

另外,构造函数里的initialState参数可以直接去掉,在super里传入SearchNewsInitial()即可。

2. Repository层API URL拼写错误

你把搜索接口的everything写成了eveything(少了一个字母r):

String url = "https://newsapi.org/v2/eveything?q=$query&apiKey=${NewsApiConstants.apiKey}";

这会导致请求返回错误,修正为:

String url = "https://newsapi.org/v2/everything?q=$query&apiKey=${NewsApiConstants.apiKey}";

3. 搜索结果页面布局限制导致显示不全

SearchedNewsResult里,你给ListView.builder设置了NeverScrollableScrollPhysicsshrinkWrap: true,还套了两层Flexible,这会让列表无法正常滚动,甚至只渲染第一条数据就被截断。

修复方法:调整布局结构,用Expanded替代冗余的Flexible,让列表占据剩余空间并正常滚动:

@override
Widget build(BuildContext context) {
  searchBloc.add(StartSearchNewsEvent(query: queryResult));
  return Scaffold(
    appBar: customAppBar('Flash News', context),
    body: Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(15.0),
          child: Text(queryResult),
        ),
        Expanded(
          child: BlocBuilder<SearchNewsBloc, SearchNewsState>(
            builder: (context, state) {
              if (state is SearchNewsLoadingState) {
                return const Center(child: CircularProgressIndicator());
              } else if (state is SearchNewsLoadedState) {
                return ListView.builder(
                  itemCount: state.articleList.length,
                  itemBuilder: (context, index) {
                    final article = state.articleList[index];
                    return NewsCard(
                      imgUrl: article.urlToImage ?? "",
                      desc: article.description ?? "",
                      title: article.title ?? "",
                      content: article.content ?? "",
                      postUrl: article.url ?? "",
                    );
                  },
                );
              } else if (state is SearchNewsErrorState) {
                return Center(child: Text(state.errorMessage));
              } else {
                return const Center(child: CircularProgressIndicator());
              }
            },
          ),
        ),
      ],
    ),
  );
}

另外,你之前给NewsCard传的imgUrlpostUrl是固定空字符串,要改成文章模型里的真实字段。

4. Equatable事件未正确重写props

你的SearchNewsEvent类里的props没有包含query字段,这会导致Equatable无法正确判断事件是否相同,可能引发重复触发或不触发事件的问题:

abstract class SearchNewsEvent extends Equatable {
  final String query;
  const SearchNewsEvent({required this.query});

  @override
  List<Object?> get props => [query]; // 必须把query加入props列表
}

按照上面的方法修复后,应该就能正常显示所有搜索结果了。

内容的提问来源于stack exchange,提问作者sulli110

火山引擎 最新活动