json - Flutter 应用 API POST 响应未返回
问题描述
我正在使用提交方法将数据发布到 REST 服务后端,并且保存方法调用此 POST 并等待来自后端的响应。
POST 的异步方法如下
Future<PetCreate> createThePet(data, apiUrl) async{
var fullUrl = _baseUrl + apiUrl; // + await _getToken();
final response = await http.post(fullUrl, body: jsonEncode(data), headers: _setHeaders());
if(response.statusCode == 200){
final String responseString = response.body;
print(responseString);
return petCreateFromJson(responseString);
}else{
return null;
}
}
这里响应即将到来,但是当我尝试将该 response.body 传递给字符串值“responseString”时,它会失败。print(responseString) 中途停止打印,'return petCreateFromJson(responseString);' 也没有被调用。
*** 数据模型 ***
PetCreate petCreateFromJson(String str) => PetCreate.fromJson(json.decode(str));
String petCreateToJson(PetCreate data) => json.encode(data.toJson());
class PetCreate {
PetCreate({
this.success,
this.pet,
});
bool success;
Pet pet;
factory PetCreate.fromJson(Map<String, dynamic> json) => PetCreate(
success: json["success"],
pet: Pet.fromJson(json["pet"]),
);
Map<String, dynamic> toJson() => {
"success": success,
"pet": pet.toJson(),
};
}
class Pet {
Pet({
this.id,
this.activityLevelName,
this.dailyAllowanceGuidelinesDetails,
this.eatbone,
this.idealWeight,
this.image,
this.name,
this.nutrientGuidelineDetail,
this.totalDailyCalories,
this.weight,
this.breed,
});
int id;
String activityLevelName;
List<DailyAllowanceGuidelinesDetail> dailyAllowanceGuidelinesDetails;
bool eatbone;
double idealWeight;
Image image;
String name;
List<NutrientGuidelineDetail> nutrientGuidelineDetail;
String totalDailyCalories;
double weight;
Breed breed;
factory Pet.fromJson(Map<String, dynamic> json) => Pet(
id: json["id"],
activityLevelName: json["activity_level_name"],
dailyAllowanceGuidelinesDetails: List<DailyAllowanceGuidelinesDetail>.from(json["daily_allowance_guidelines_details"].map((x) => DailyAllowanceGuidelinesDetail.fromJson(x))),
eatbone: json["eatbone"],
idealWeight: json["ideal_weight"].toDouble(),
image: Image.fromJson(json["image"]),
name: json["name"],
nutrientGuidelineDetail: List<NutrientGuidelineDetail>.from(json["nutrient_guideline_detail"].map((x) => NutrientGuidelineDetail.fromJson(x))),
totalDailyCalories: json["total_daily_calories"],
weight: json["weight"].toDouble(),
breed: Breed.fromJson(json["breed"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"activity_level_name": activityLevelName,
"daily_allowance_guidelines_details": List<dynamic>.from(dailyAllowanceGuidelinesDetails.map((x) => x.toJson())),
"eatbone": eatbone,
"ideal_weight": idealWeight,
"image": image.toJson(),
"name": name,
"nutrient_guideline_detail": List<dynamic>.from(nutrientGuidelineDetail.map((x) => x.toJson())),
"total_daily_calories": totalDailyCalories,
"weight": weight,
"breed": breed.toJson(),
};
}
class Breed {
Breed({
this.id,
this.creatorId,
this.updaterId,
this.deleterId,
this.deletedAt,
this.giant,
this.name,
this.createdAt,
this.updatedAt,
});
int id;
dynamic creatorId;
dynamic updaterId;
dynamic deleterId;
dynamic deletedAt;
dynamic giant;
String name;
DateTime createdAt;
DateTime updatedAt;
factory Breed.fromJson(Map<String, dynamic> json) => Breed(
id: json["id"],
creatorId: json["creator_id"],
updaterId: json["updater_id"],
deleterId: json["deleter_id"],
deletedAt: json["deleted_at"],
giant: json["giant"],
name: json["name"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"creator_id": creatorId,
"updater_id": updaterId,
"deleter_id": deleterId,
"deleted_at": deletedAt,
"giant": giant,
"name": name,
"created_at": createdAt.toIso8601String(),
"updated_at": updatedAt.toIso8601String(),
};
}
class DailyAllowanceGuidelinesDetail {
DailyAllowanceGuidelinesDetail({
this.name,
this.bones,
this.percentage,
});
String name;
bool bones;
int percentage;
factory DailyAllowanceGuidelinesDetail.fromJson(Map<String, dynamic> json) => DailyAllowanceGuidelinesDetail(
name: json["name"],
bones: json["bones"],
percentage: json["percentage"],
);
Map<String, dynamic> toJson() => {
"name": name,
"bones": bones,
"percentage": percentage,
};
}
class Image {
Image({
this.url,
this.thumb,
});
dynamic url;
Thumb thumb;
factory Image.fromJson(Map<String, dynamic> json) => Image(
url: json["url"],
thumb: Thumb.fromJson(json["thumb"]),
);
Map<String, dynamic> toJson() => {
"url": url,
"thumb": thumb.toJson(),
};
}
class Thumb {
Thumb({
this.url,
});
dynamic url;
factory Thumb.fromJson(Map<String, dynamic> json) => Thumb(
url: json["url"],
);
Map<String, dynamic> toJson() => {
"url": url,
};
}
class NutrientGuidelineDetail {
NutrientGuidelineDetail({
this.name,
this.amount,
this.unit,
});
String name;
double amount;
Unit unit;
factory NutrientGuidelineDetail.fromJson(Map<String, dynamic> json) => NutrientGuidelineDetail(
name: json["name"],
amount: json["amount"].toDouble(),
unit: unitValues.map[json["unit"]],
);
Map<String, dynamic> toJson() => {
"name": name,
"amount": amount,
"unit": unitValues.reverse[unit],
};
}
enum Unit { G, RATIO, MG, MCG }
final unitValues = EnumValues({
"g": Unit.G,
"mcg": Unit.MCG,
"mg": Unit.MG,
"ratio": Unit.RATIO
});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
来自 API 的示例响应如下所示
{
"success": true,
"pet": {
"id": 31,
"activity_level_name": "Low Activity (<1hr/day)",
"daily_allowance_guidelines_details": [
{
"name": "Muscle Meat",
"bones": true,
"percentage": 60
},
{
"name": "Organ Meat",
"bones": false,
"percentage": 10
},
{
"name": "Fruit and Veg",
"bones": false,
"percentage": 20
},
{
"name": "Bone",
"bones": true,
"percentage": 10
}
],
"eatbone": true,
"ideal_weight": 4.4,
"image": {
"url": null,
"thumb": {
"url": null
}
},
"name": "petsy",
"nutrient_guideline_detail": [
{
"name": "Protein",
"amount": 12.54,
"unit": "g"
},
{
"name": "Crude fat",
"amount": 3.85,
"unit": "g"
},
{
"name": "Calcium/Phosphorus ratio",
"amount": 0.56,
"unit": "ratio"
},
{
"name": "Omega-3/6 ratio",
"amount": 0.07,
"unit": "ratio"
},
{
"name": "Omega-6",
"amount": 0.78,
"unit": "g"
},
{
"name": "Omega-3 excl. ALA and SDA",
"amount": 0.03,
"unit": "g"
},
{
"name": "Calcium",
"amount": 0.35,
"unit": "g"
},
{
"name": "Phosphorus",
"amount": 0.28,
"unit": "g"
},
{
"name": "Potassium",
"amount": 0.42,
"unit": "g"
},
{
"name": "Sodium (Na)",
"amount": 0.06,
"unit": "mg"
},
{
"name": "Magnesium",
"amount": 0.04,
"unit": "mg"
},
{
"name": "Iron",
"amount": 2.79,
"unit": "mg"
},
{
"name": "Copper",
"amount": 0.51,
"unit": "mg"
},
{
"name": "Manganese",
"amount": 0.35,
"unit": "mg"
},
{
"name": "Zinc (Zn)",
"amount": 5.57,
"unit": "mg"
},
{
"name": "Iodine",
"amount": 69.68,
"unit": "mcg"
},
{
"name": "Selenium",
"amount": 0.02,
"unit": "mcg"
},
{
"name": "Vitamin A",
"amount": 104.52,
"unit": "mcg"
},
{
"name": "Vitamin D",
"amount": 0.86,
"unit": "mcg"
},
{
"name": "Vitamin E",
"amount": 3.14,
"unit": "mg"
},
{
"name": "Thiamin (B1)",
"amount": 0.16,
"unit": "mg"
},
{
"name": "Riboflavin (B2)",
"amount": 0.36,
"unit": "mg"
},
{
"name": "Niacin (B3)",
"amount": 0.95,
"unit": "mg"
},
{
"name": "Pantothenic acid (B5)",
"amount": 0.84,
"unit": "mg"
},
{
"name": "Folate",
"amount": 15.05,
"unit": "mcg"
},
{
"name": "Choline",
"amount": 94.76,
"unit": "mg"
},
{
"name": "Vitamin C",
"amount": 0,
"unit": "mg"
}
],
"total_daily_calories": "278.72",
"weight": 4.2,
"breed": {
"id": 1,
"creator_id": null,
"updater_id": null,
"deleter_id": null,
"deleted_at": null,
"giant": null,
"name": "Abyssinian San Terrier",
"created_at": "2020-09-24T16:41:36.111+09:30",
"updated_at": "2020-09-24T16:41:36.111+09:30"
}
}
}
当我尝试做
Future<PetCreate> createThePet(data, apiUrl) async{
var fullUrl = _baseUrl + apiUrl; // + await _getToken();
final response = await http.post(fullUrl, body: jsonEncode(data), headers: _setHeaders());
if(response.statusCode == 200){
var responseString = response.body;
//print(responseString);
return null; //petCreateFromJson(responseString);
}else{
return null;
}
}
代码执行
savePetData(BuildContext ctx) async {
//dogData here
final PetCreate pet = await CallApi().createThePet(dogData, 'pets/create');
setState(() {
_pet = pet;
});
print('///////////////////////// success //////////////////////////');
if (_pet.success) {
petPrefs = await SharedPreferences.getInstance();
petPrefs.setString('pet_image', _pet.pet.image.thumb.url);
等等 。如果我按照我提到的那样运行代码而不进行更改,它会在此处停止'final PetCreate pet = await CallApi().createThePet(dogData,' 并再次跳转到方法调用'savePetData(BuildContext ctx)'
有人可以帮我弄清楚这里发生了什么,我该怎么办?
解决方案
await
在调用之前使用savePetData()
,以便等待函数执行完成。
Future<void> _handleSubmit(BuildContext context) async {
setState(() {
_isLoading = true;
});
LoadingDialog.showLoadingDialog(context, _petFormKey);
await savePetData();
setState(() {
_isLoading = false;
});
}
推荐阅读
- typescript - 在 Typescript 中将类型作为对象或数组访问
- python - Python中现有数据框中的多头和子头
- excel - 通过实时更新计算指定日期的天数
- python - 来自DF的Python堆积条形图与索引日期?
- javascript - 如何在 PHP Laravel 中创建具有过滤日期不同功能的选择按钮?
- python - 在没有 ChromeDriver 的情况下使用 selenium
- python - python sklearn.decomposition FactorAnalysis 函数
- azure - 在 Azure 应用服务中写入新文件?
- javascript - 有没有办法使用jQuery和/或CSS通过单击按钮来反转页面上的所有颜色?
- python - RabbitMQ、Flask/fastapi 和 websockets