#json #rest #flutter
#json #отдых #флаттер
Вопрос:
Я использую метод отправки для отправки данных в серверную часть службы REST, а метод сохранения вызывает это СООБЩЕНИЕ и ожидает ответа от серверной части.
асинхронный метод для 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;
}
}
здесь приходит ответ, но когда я пытаюсь передать этот ответ.тело для строкового значения ‘responseString’ завершается ошибкой. печать (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)’
может ли кто-нибудь помочь мне разобраться, что здесь происходит, и что мне с этим делать?
Ответ №1:
Используйте await
перед вызовом savePetData()
, чтобы он ожидал завершения выполнения функции.
Future<void> _handleSubmit(BuildContext context) async {
setState(() {
_isLoading = true;
});
LoadingDialog.showLoadingDialog(context, _petFormKey);
await savePetData();
setState(() {
_isLoading = false;
});
}
Комментарии:
1. спасибо за ввод, но это не сработало., проблема сохраняется. Он дважды вызывает savePetData() .
2. куда
_handleSubmit
вызывается вызов?3. он вызывается внутри FlatButton для onPressed(), который находится внутри showModalBottomScheet . мое намерение таково> пользователь вводит данные регистра для питомца. при сохранении будет вызван modalBottomSheet, затем есть два варианта позже и хорошо. в любом из этих двух в FlatButton onPressed() вызывается _handleSubmit . в случае успеха после отправки мне нужно закрыть modalBottomSheet, а затем перейти с этого экрана на новый.
4. Проверьте свои вызовы setState, они выглядят неорганизованными. попробуйте установить точки останова или принять логическое значение и проверить перед вызовом savePetData, вызывался ли он ранее, чтобы узнать, когда он вызывается дважды.
5. не могли бы вы помочь мне в моем коде, если это не проблема для вас, пожалуйста? очень полезно