提问人:PlayzAhmed 提问时间:11/10/2023 最后编辑:Brian Tompsett - 汤莱恩PlayzAhmed 更新时间:11/10/2023 访问量:26
我希望在屏幕上查看来自 API 的食物数据,并显示营养详细信息
I want food data from an API to be viewed with nutrients detail in my screen
问:
当我点击食物时,我想查看应用程序加载的营养成分,然后给我一个空屏幕,如向下所述,我需要在屏幕上显示营养成分而不给出空。 这是我的详细信息屏幕,应在此处查看营养详细信息:
详细信息屏幕:
class DetailScreen extends StatefulWidget {
final int id;
DetailScreen(this.id);
@override
_DetailSreenState createState() => _DetailSreenState();
}
class _DetailSreenState extends State<DetailScreen> {
FoodData? foodData;
bool loading = true;
@override
void initState() {
fetchData();
super.initState();
}
Future<void> fetchData() async {
try {
var url = Uri.parse('https://api.nal.usda.gov/fdc/v1/food/${widget.id}?api_key=DEMO_KEY');
var response = (await http.get(url));
final decodedResponse = convert.jsonDecode(response.body);
foodData = FoodData.fromMap(decodedResponse);
setState(() {
loading = false;
});
} catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: loading ? SizedBox.shrink(): Text("${foodData?.description}", style: TextStyle(fontSize: 20),),),
body: Container(
child: loading? CircularProgressIndicator():Column(
children: [
Text("Portion: per 100g", style: TextStyle(fontSize: 25),),
Container(
child: Expanded(
child: ListView.builder(
itemCount: foodData == null? 0: foodData?.foodNutrients.length,
itemBuilder: (context , index){
return Padding(
padding: const EdgeInsets.all(10.0),
child: Text("${foodData?.foodNutrients[index].nutrient.name}:"
"${foodData?.foodNutrients[index].amount}"
"${foodData?.foodNutrients[index].amount == null ? "" : foodData?.foodNutrients[index].nutrient.unitName}",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: Colors.black54), ),
);
}),
),
)
],
),
),
);
}
}
这是我的食物模型文件
食品型号 :
FoodData foodDataFromJson(String str) => FoodData.fromJson(json.decode(str));
String foodDataToJson(FoodData data) => json.encode(data.toJson());
class FoodData {
String? foodClass;
String? description;
List<FoodNutrient> foodNutrients;
List<FoodAttribute> foodAttributes;
String? foodCode;
String? startDate;
String? endDate;
WweiaFoodCategory wweiaFoodCategory;
String? dataType;
String? fdcId;
List<FoodPortion> foodPortions;
String? publicationDate;
List<InputFood> inputFoods;
FoodData({
required this.foodClass,
required this.description,
required this.foodNutrients,
required this.foodAttributes,
required this.foodCode,
required this.startDate,
required this.endDate,
required this.wweiaFoodCategory,
required this.dataType,
required this.fdcId,
required this.foodPortions,
required this.publicationDate,
required this.inputFoods,
});
FoodData copyWith({
String? foodClass,
String? description,
List<FoodNutrient>? foodNutrients,
List<FoodAttribute>? foodAttributes,
String? foodCode,
String? startDate,
String? endDate,
WweiaFoodCategory? wweiaFoodCategory,
String? dataType,
String? fdcId,
List<FoodPortion>? foodPortions,
String? publicationDate,
List<InputFood>? inputFoods,
}) =>
FoodData(
foodClass: foodClass ?? this.foodClass,
description: description ?? this.description,
foodNutrients: foodNutrients ?? this.foodNutrients,
foodAttributes: foodAttributes ?? this.foodAttributes,
foodCode: foodCode ?? this.foodCode,
startDate: startDate ?? this.startDate,
endDate: endDate ?? this.endDate,
wweiaFoodCategory: wweiaFoodCategory ?? this.wweiaFoodCategory,
dataType: dataType ?? this.dataType,
fdcId: fdcId ?? this.fdcId,
foodPortions: foodPortions ?? this.foodPortions,
publicationDate: publicationDate ?? this.publicationDate,
inputFoods: inputFoods ?? this.inputFoods,
);
factory FoodData.fromJson(Map<String, dynamic> json) => FoodData(
foodClass: json["foodClass"],
description: json["description"],
foodNutrients: List<FoodNutrient>.from(json["foodNutrients"].map((x) => FoodNutrient.fromJson(x))),
foodAttributes: List<FoodAttribute>.from(json["foodAttributes"].map((x) => FoodAttribute.fromJson(x))),
foodCode: json["foodCode"],
startDate: json["startDate"],
endDate: json["endDate"],
wweiaFoodCategory: WweiaFoodCategory.fromJson(json["wweiaFoodCategory"]),
dataType: json["dataType"],
fdcId: json["fdcId"].toString(),
foodPortions: List<FoodPortion>.from(json["foodPortions"].map((x) => FoodPortion.fromJson(x))),
publicationDate: json["publicationDate"],
inputFoods: List<InputFood>.from(json["inputFoods"].map((x) => InputFood.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"foodClass": foodClass,
"description": description,
"foodNutrients": List<dynamic>.from(foodNutrients.map((x) => x.toJson())),
"foodAttributes": List<dynamic>.from(foodAttributes.map((x) => x.toJson())),
"foodCode": foodCode,
"startDate": startDate,
"endDate": endDate,
"wweiaFoodCategory": wweiaFoodCategory.toJson(),
"dataType": dataType,
"fdcId": fdcId,
"foodPortions": List<dynamic>.from(foodPortions.map((x) => x.toJson())),
"publicationDate": publicationDate,
"inputFoods": List<dynamic>.from(inputFoods.map((x) => x.toJson())),
};
static fromMap(decodedResponse) {}
}
class FoodAttribute {
int id;
String? name;
String value;
FoodAttributeType foodAttributeType;
String? rank;
FoodAttribute({
required this.id,
this.name,
required this.value,
required this.foodAttributeType,
this.rank,
});
FoodAttribute copyWith({
int? id,
String? name,
String? value,
FoodAttributeType? foodAttributeType,
String? rank,
}) =>
FoodAttribute(
id: id ?? this.id,
name: name ?? this.name,
value: value ?? this.value,
foodAttributeType: foodAttributeType ?? this.foodAttributeType,
rank: rank ?? this.rank,
);
factory FoodAttribute.fromJson(Map<String, dynamic> json) => FoodAttribute(
id: json["id"],
name: json["name"],
value: json["value"],
foodAttributeType: FoodAttributeType.fromJson(json["foodAttributeType"]),
rank: json["rank"].toString(),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"value": value,
"foodAttributeType": foodAttributeType.toJson(),
"rank": rank,
};
}
class FoodAttributeType {
int id;
String name;
String description;
FoodAttributeType({
required this.id,
required this.name,
required this.description,
});
FoodAttributeType copyWith({
int? id,
String? name,
String? description,
}) =>
FoodAttributeType(
id: id ?? this.id,
name: name ?? this.name,
description: description ?? this.description,
);
factory FoodAttributeType.fromJson(Map<String, dynamic> json) => FoodAttributeType(
id: json["id"],
name: json["name"],
description: json["description"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"description": description,
};
}
class FoodNutrient {
Type type;
int id;
Nutrient nutrient;
double amount;
FoodNutrient({
required this.type,
required this.id,
required this.nutrient,
required this.amount,
});
FoodNutrient copyWith({
Type? type,
int? id,
Nutrient? nutrient,
double? amount,
}) =>
FoodNutrient(
type: type ?? this.type,
id: id ?? this.id,
nutrient: nutrient ?? this.nutrient,
amount: amount ?? this.amount,
);
factory FoodNutrient.fromJson(Map<String, dynamic> json) => FoodNutrient(
type: typeValues.map[json["type"]]!,
id: json["id"],
nutrient: Nutrient.fromJson(json["nutrient"]),
amount: json["amount"]?.toDouble(),
);
Map<String, dynamic> toJson() => {
"type": typeValues.reverse[type],
"id": id,
"nutrient": nutrient.toJson(),
"amount": amount,
};
}
class Nutrient {
int id;
String number;
String name;
String rank;
String unitName;
Nutrient({
required this.id,
required this.number,
required this.name,
required this.rank,
required this.unitName,
});
Nutrient copyWith({
int? id,
String? number,
String? name,
String? rank,
String? unitName,
}) =>
Nutrient(
id: id ?? this.id,
number: number ?? this.number,
name: name ?? this.name,
rank: rank ?? this.rank,
unitName: unitName ?? this.unitName,
);
factory Nutrient.fromJson(Map<String, dynamic> json) => Nutrient(
id: json["id"],
number: json["number"],
name: json["name"],
rank: json["rank"].toString(),
unitName: json["unitName"],
);
Map<String, dynamic> toJson() => {
"id": id,
"number": number,
"name": name,
"rank": rank,
"unitName": unitNameValues.reverse[unitName],
};
}
enum UnitName {
G,
KCAL,
MG,
UNIT_NAME_G
}
final unitNameValues = EnumValues({
"g": UnitName.G,
"kcal": UnitName.KCAL,
"mg": UnitName.MG,
"µg": UnitName.UNIT_NAME_G
});
enum Type {
FOOD_NUTRIENT
}
final typeValues = EnumValues({
"FoodNutrient": Type.FOOD_NUTRIENT
});
class FoodPortion {
int id;
MeasureUnit measureUnit;
String modifier;
String gramWeight;
String sequenceNumber;
String portionDescription;
FoodPortion({
required this.id,
required this.measureUnit,
required this.modifier,
required this.gramWeight,
required this.sequenceNumber,
required this.portionDescription,
});
FoodPortion copyWith({
int? id,
MeasureUnit? measureUnit,
String? modifier,
String? gramWeight,
String? sequenceNumber,
String? portionDescription,
}) =>
FoodPortion(
id: id ?? this.id,
measureUnit: measureUnit ?? this.measureUnit,
modifier: modifier ?? this.modifier,
gramWeight: gramWeight ?? this.gramWeight,
sequenceNumber: sequenceNumber ?? this.sequenceNumber,
portionDescription: portionDescription ?? this.portionDescription,
);
factory FoodPortion.fromJson(Map<String, dynamic> json) => FoodPortion(
id: json["id"],
measureUnit: MeasureUnit.fromJson(json["measureUnit"]),
modifier: json["modifier"],
gramWeight: json["gramWeight"].toString(),
sequenceNumber: json["sequenceNumber"].toString(),
portionDescription: json["portionDescription"],
);
Map<String, dynamic> toJson() => {
"id": id,
"measureUnit": measureUnit.toJson(),
"modifier": modifier,
"gramWeight": gramWeight,
"sequenceNumber": sequenceNumber,
"portionDescription": portionDescription,
};
}
class MeasureUnit {
int id;
String name;
String abbreviation;
MeasureUnit({
required this.id,
required this.name,
required this.abbreviation,
});
MeasureUnit copyWith({
int? id,
String? name,
String? abbreviation,
}) =>
MeasureUnit(
id: id ?? this.id,
name: name ?? this.name,
abbreviation: abbreviation ?? this.abbreviation,
);
factory MeasureUnit.fromJson(Map<String, dynamic> json) => MeasureUnit(
id: json["id"],
name: json["name"],
abbreviation: json["abbreviation"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"abbreviation": abbreviation,
};
}
class InputFood {
int id;
String unit;
String portionDescription;
String portionCode;
String foodDescription;
String sequenceNumber;
String ingredientWeight;
String ingredientCode;
String ingredientDescription;
String amount;
InputFood({
required this.id,
required this.unit,
required this.portionDescription,
required this.portionCode,
required this.foodDescription,
required this.sequenceNumber,
required this.ingredientWeight,
required this.ingredientCode,
required this.ingredientDescription,
required this.amount,
});
InputFood copyWith({
int? id,
String? unit,
String? portionDescription,
String? portionCode,
String? foodDescription,
String? sequenceNumber,
String? ingredientWeight,
String? ingredientCode,
String? ingredientDescription,
String? amount,
}) =>
InputFood(
id: id ?? this.id,
unit: unit ?? this.unit,
portionDescription: portionDescription ?? this.portionDescription,
portionCode: portionCode ?? this.portionCode,
foodDescription: foodDescription ?? this.foodDescription,
sequenceNumber: sequenceNumber ?? this.sequenceNumber,
ingredientWeight: ingredientWeight ?? this.ingredientWeight,
ingredientCode: ingredientCode ?? this.ingredientCode,
ingredientDescription: ingredientDescription ?? this.ingredientDescription,
amount: amount ?? this.amount,
);
factory InputFood.fromJson(Map<String, dynamic> json) => InputFood(
id: json["id"],
unit: json["unit"],
portionDescription: json["portionDescription"],
portionCode: json["portionCode"],
foodDescription: json["foodDescription"],
sequenceNumber: json["sequenceNumber"].toString(),
ingredientWeight: json["ingredientWeight"].toString(),
ingredientCode: json["ingredientCode"].toString(),
ingredientDescription: json["ingredientDescription"],
amount: json["amount"],
);
Map<String, dynamic> toJson() => {
"id": id,
"unit": unit,
"portionDescription": portionDescription,
"portionCode": portionCode,
"foodDescription": foodDescription,
"sequenceNumber": sequenceNumber,
"ingredientWeight": ingredientWeight,
"ingredientCode": ingredientCode,
"ingredientDescription": ingredientDescription,
"amount": amount,
};
}
class WweiaFoodCategory {
String wweiaFoodCategoryCode;
String wweiaFoodCategoryDescription;
WweiaFoodCategory({
required this.wweiaFoodCategoryCode,
required this.wweiaFoodCategoryDescription,
});
WweiaFoodCategory copyWith({
String? wweiaFoodCategoryCode,
String? wweiaFoodCategoryDescription,
}) =>
WweiaFoodCategory(
wweiaFoodCategoryCode: wweiaFoodCategoryCode ?? this.wweiaFoodCategoryCode,
wweiaFoodCategoryDescription: wweiaFoodCategoryDescription ?? this.wweiaFoodCategoryDescription,
);
factory WweiaFoodCategory.fromJson(Map<String, dynamic> json) => WweiaFoodCategory(
wweiaFoodCategoryCode: json["wweiaFoodCategoryCode"].toString(),
wweiaFoodCategoryDescription: json["wweiaFoodCategoryDescription"].toString(),
);
Map<String, dynamic> toJson() => {
"wweiaFoodCategoryCode": wweiaFoodCategoryCode,
"wweiaFoodCategoryDescription": wweiaFoodCategoryDescription,
};
}
class EnumValues<T> {
Map<String, T> map;
late Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
reverseMap = map.map((k, v) => MapEntry(v, k));
return reverseMap;
}
}
当我使用该应用程序时,我得到了 null:
答:
0赞
Surya
11/10/2023
#1
使用值通知程序更新屏幕,如下所示
详细信息屏幕
class DetailScreen extends StatefulWidget {
final int id;
DetailScreen(this.id);
@override
_DetailSreenState createState() => _DetailSreenState();
}
class _DetailSreenState extends State<DetailScreen> {
FoodData? foodData;
ValueNotifier<bool> loading = ValueNotifier(true);
@override
void initState() {
fetchData();
super.initState();
}
Future<void> fetchData() async {
print("****** fetching Data *********");
try {
loading.value = true;
var url = Uri.parse('https://api.nal.usda.gov/fdc/v1/food/${widget.id}?api_key=DEMO_KEY');
var response = (await http.get(url));
final decodedResponse = json.decode(response.body);
foodData = FoodData.fromMap(decodedResponse);
loading.value = false;
} catch (e) {
print("****** fetching Data error *********");
print(e);
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ValueListenableBuilder<bool>(
valueListenable: loading,
builder: (context, loadingVal, _) {
return Scaffold(
appBar: AppBar(
title: loadingVal
? SizedBox.shrink()
: Text(
"${foodData?.description}",
style: TextStyle(fontSize: 20),
),
),
body: Container(
child: loadingVal
? CircularProgressIndicator()
: Column(
children: [
Text(
"Portion: per 100g",
style: TextStyle(fontSize: 25),
),
Container(
child: Expanded(
child: ListView.builder(
itemCount: foodData == null ? 0 : foodData?.foodNutrients.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
"${foodData?.foodNutrients[index].nutrient.name}:"
"${foodData?.foodNutrients[index].amount}"
"${foodData?.foodNutrients[index].amount == null ? "" : foodData?.foodNutrients[index].nutrient.unitName}",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: Colors.black54),
),
);
}),
),
)
],
),
),
);
}));
}
}
注 - 如果 api 中有空值,请确保您正在处理 null 检查并显示正确的屏幕
评论