错误状态:使用firstWhere函数时没有元素



当我试图将从路由中获得的参数与列表的值进行比较时,上面出现了这个错误。

MealDetailScreen小部件

import 'package:flutter/material.dart';
import '../dummy_data.dart';
class MealDetailScreen extends StatelessWidget {
static const detailScreenRouteName = '/meal-detail';
@override
Widget build(BuildContext context) {
final mealId = ModalRoute.of(context)!.settings.arguments;
final selectedMeal = DUMMY_MEALS.firstWhere((meal) => meal.id == mealId);
return Scaffold(
appBar: AppBar(title: Text('$mealId')),
body: Container(
child: Column(
children: [
Container(
height: 300,
width: double.infinity,
child: Image.network(
selectedMeal.imageUrl,
fit: BoxFit.cover,
),
)
],
),
),
);
}
}

如果我试图将可选参数"orElse"添加到firstWhere函数中,我仍然会收到一个错误:这次是返回类型"Null"不是"Meal",这是闭包上下文所要求的

这是我用来比较id的列表。

const DUMMY_MEALS = [
Meal(
isVegetarian: false,
isLactoseFree: false,
isVegan: false,
id: 'm1',
categories: [
'c1',
'c2',
],
title: 'Spaghetti with Tomato Sauce',
affordability: Affordability.Affordable,
complexity: Complexity.Simple,
imageUrl: '...',
duration: 20,
ingredients: ['4 Tomatoes', '...'],
steps: ['Cut the tomatoes and the onion into small pieces.', '...'],
isGlutenFree: false,
),
];

这就是我将id作为参数传递的方式

void selectMeal(BuildContext context) {
Navigator.of(context)
.pushNamed(MealDetailScreen.detailScreenRouteName, arguments: {id});
}

膳食模型

import 'package:flutter/foundation.dart';
enum Complexity { Simple, Challenging, Hard }
enum Affordability { Affordable, Pricey, Luxurious }
class Meal {
final String id;
final List<String> categories;
final String title;
final String imageUrl;
final List<String> ingredients;
final List<String> steps;
final int duration;
final Complexity complexity;
final Affordability affordability;
final bool isGlutenFree;
final bool isLactoseFree;
final bool isVegan;
final bool isVegetarian;
const Meal(
{required this.id,
required this.categories,
required this.title,
required this.imageUrl,
required this.ingredients,
required this.steps,
required this.duration,
required this.complexity,
required this.affordability,
required this.isGlutenFree,
required this.isLactoseFree,
required this.isVegan,
required this.isVegetarian});
}

在传递arguments: {id}时,您正在传递_HashSet<String>。但对于单个值id字符串就足够了,否则使用映射。

在这种情况下,传递参数将是

Navigator.of(context)
.pushNamed(MealDetailScreen.detailScreenRouteName, arguments: id);

在迭代DUMMY_MEALS列表时,我们可能会得到一个不包括在DUMMY_MEALS列表中的id。在这种情况下,您可以在orElse状态下创建并传递emptyMeal,或者只使用try catch来处理异常。


Meal? selectedMeal;
try {
final selectedMeal = DUMMY_MEALS.firstWhere((meal) => meal.id == mealId);
} catch (e) {
print(e.toString());
}

虽然selectedMeal可以为空,但我们可以检查它是否包含膳食。

return Scaffold(
appBar: AppBar(title: Text('$mealId')),
body: selectedMeal == null
? Text("Cound not find data")
: Container(
child: Column(
children: [
Text(selectedMeal.title),
],
),
),
);

答案已经给出。但我想指出的是,如果您使用pushNamed方法,它建议您使用onGenerateRoute来管理传递参数。因此,您不需要null校验参数或上下文。

ModalRoute.of(context)?.settings?.arguments? 
MaterialApp(
onGenerateRoute: (settings) {
if (settings.name == PassArgumentsScreen.routeName) {
final args = settings.arguments as ScreenArguments;
return MaterialPageRoute(
builder: (context) {
return PassArgumentsScreen(
title: args.title,
message: args.message,
);
},
);
}
assert(false, 'Need to implement ${settings.name}');
return null;
},
)

引用:将参数传递给命名路由

相关内容

  • 没有找到相关文章

最新更新