Flutter使用firstWhere函数报Bad State: no element错误如何解决
问题根因
- 路由传参格式错误:你在
selectMeal方法中传递参数时写了arguments: {id},外层大括号会将id包裹为Set集合类型,而Meal类的id字段是String类型,二者类型不一致导致meal.id == mealId的判断永远不成立,firstWhere找不到匹配元素就抛出Bad State: no element错误。 - 新增
orElse后报错的原因:Dart中firstWhere的返回值类型和列表元素类型保持一致,如果你直接在orElse闭包中返回Null,和列表的Meal类型不匹配,就会触发类型校验报错。
解决步骤
- 修正路由传参格式,去掉包裹id的大括号,直接传递String类型的id:
void selectMeal(BuildContext context) { Navigator.of(context) .pushNamed(MealDetailScreen.detailScreenRouteName, arguments: id); }
- 在详情页做强类型校验,同时添加找不到匹配数据的兜底逻辑,两种可选方案:
方案1:用orElse返回默认值
@override Widget build(BuildContext context) { // 强转参数为String类型,提前暴露类型错误 final mealId = ModalRoute.of(context)!.settings.arguments as String; final selectedMeal = DUMMY_MEALS.firstWhere( (meal) => meal.id == mealId, // 找不到匹配数据时返回默认餐品,可根据业务需求自定义 orElse: () => DUMMY_MEALS.first(), ); // 原有渲染逻辑不变 return Scaffold( appBar: AppBar(title: Text(selectedMeal.title)), body: Container( child: Column( children: [ Container( height: 300, width: double.infinity, child: Image.network( selectedMeal.imageUrl, fit: BoxFit.cover, ), ) ], ), ), ); }
方案2:提前判断匹配结果,找不到直接返回上一页提示
@override Widget build(BuildContext context) { final mealId = ModalRoute.of(context)!.settings.arguments as String; final matchedMeals = DUMMY_MEALS.where((meal) => meal.id == mealId); // 无匹配数据时提示并返回 if (matchedMeals.isEmpty) { WidgetsBinding.instance.addPostFrameCallback((_) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('未找到对应餐品'))); Navigator.of(context).pop(); }); return const Scaffold(body: Center(child: CircularProgressIndicator())); } final selectedMeal = matchedMeals.first; // 原有渲染逻辑不变 return Scaffold( appBar: AppBar(title: Text(selectedMeal.title)), body: Container( child: Column( children: [ Container( height: 300, width: double.infinity, child: Image.network( selectedMeal.imageUrl, fit: BoxFit.cover, ), ) ], ), ), ); }
内容的提问来源于stack exchange,提问作者Cláudio Vitor Dantas
相关产品推荐
相关产品推荐

