Flutter使用SearchDelegate时出现The method 'where' was called on null报错如何解决
问题排查与修复方案
核心问题点
- 代码执行顺序错误:FutureBuilder中你先执行了
routes.where过滤逻辑,后判断routes == null,当Future还未完成/请求失败时routes为null,直接调用where方法就会触发空引用报错 - 重复变量定义:
buildResults方法中连续两次定义List<RouteWithStops> routes,第一次取值为snapshot.data,第二次直接覆盖为空数组,会导致搜索逻辑完全失效 - 重复请求冗余:每次输入字符都会触发
buildSuggestions重新执行,每次都会重新调用getMarshrutWithStops请求接口,容易出现请求延迟导致的null问题
修复代码示例
1. 修复buildSuggestions方法
@override Widget buildSuggestions(BuildContext context) { return FutureBuilder<List<RouteWithStops>>( // 明确指定泛型,避免dynamic类型隐患 future: service.getMarshrutWithStops(ttId), builder: (BuildContext context, AsyncSnapshot<List<RouteWithStops>> snapshot) { // 先判断状态,再处理业务逻辑 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError || !snapshot.hasData) { return const Center(child: Text("暂无数据")); } final routes = snapshot.data!; const recentRoutes = <RouteWithStops>[]; final suggestion = query.isEmpty ? recentRoutes : routes .where((element) => element.route.mrTitle.startsWith(query)) .toList(); return ListView.builder( itemCount: suggestion.length, itemBuilder: (context, index) { final mrTitle = suggestion[index].route.mrTitle; return ListTile( onTap: () => close(context, suggestion[index]), title: RichText( text: TextSpan( children: [ TextSpan( text: mrTitle.substring(0, query.length), style: const TextStyle( color: Colors.black, fontWeight: FontWeight.bold), ), TextSpan( text: mrTitle.substring(query.length), style: const TextStyle(color: Colors.black), ), ], ), ), ); }); }); }
2. 修复buildResults方法
@override Widget buildResults(BuildContext context) { // 可直接复用buildSuggestions逻辑,无需重复写代码 return buildSuggestions(context); }
优化建议
- 可以把
getMarshrutWithStops的请求结果缓存在SearchDelegate内部,每次build时优先用缓存数据,避免频繁请求接口 - 可以加防抖逻辑,用户输入停顿300ms后再执行过滤,减少不必要的逻辑执行
内容的提问来源于stack exchange,提问作者user16357470
相关产品推荐
相关产品推荐

