I’m having this error above when I try to compare the parameter I get from the route with the value of a list.
MealDetailScreen widget
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,
),
)
],
),
),
);
}
}
If i try to add the optional argument 'orElse' to the firstWhere function i still get an error: this time it is The return type 'Null' isn't a 'Meal', as required by the closure's context.
This is the list im using to compare the 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,
),
];
And this is how i pass the id as parameter
void selectMeal(BuildContext context) {
Navigator.of(context)
.pushNamed(MealDetailScreen.detailScreenRouteName, arguments: {id});
}
Meal model
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});
}
CodePudding user response:
While passing arguments: {id}
you are passing _HashSet<String>
. But for single value id
string will be enough, else use map.
In this case passing argument will be
Navigator.of(context)
.pushNamed(MealDetailScreen.detailScreenRouteName, arguments: id);
While iterating the DUMMY_MEALS
list it is possible that we will get an id
that is not included on DUMMY_MEALS
list. In this case you can create and pass emptyMeal on orElse
state or just use try catch
to handle exception.
Meal? selectedMeal;
try {
final selectedMeal = DUMMY_MEALS.firstWhere((meal) => meal.id == mealId);
} catch (e) {
print(e.toString());
}
While the selectedMeal
is nullable, we can check if it contains meal or not.
return Scaffold(
appBar: AppBar(title: Text('$mealId')),
body: selectedMeal == null
? Text("Cound not find data")
: Container(
child: Column(
children: [
Text(selectedMeal.title),
],
),
),
);
CodePudding user response:
The answer has been given. But I want mention that if you're using pushNamed method, it recommended that you manage passing parameters with onGenerateRoute . So you don't have nullcheck arguments or context needed.
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;
},
)