0

I'm using a submit method to POST data to a REST service backend and the save method calls this POST and awaits a Response from the backend.

the async method for POST as follows

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;
    }
  }

here the response is coming but when I try to pass that response.body to String value 'responseString' it gets failed. the print(responseString) stops printing half way through, and the 'return petCreateFromJson(responseString);' is not being invoked either.

*** data model ***

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;
  }
}

a sample response from API looks like this

{
  "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"
    }
  }
}

when I try to do

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;
    }
  }

the code executes

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);

and so on . if I run the code without changing as I mentioned, it stops here ' final PetCreate pet = await CallApi().createThePet(dogData, ' and again jumps to the method call 'savePetData(BuildContext ctx)'

can some one help me to figure out what's going on here, and what should I do about this?

1 Answer 1

1

Use await before calling savePetData(), so that it waits until the function execution is finished.

Future<void> _handleSubmit(BuildContext context) async {
    setState(() {
      _isLoading = true;
    });
    LoadingDialog.showLoadingDialog(context, _petFormKey);
    await savePetData();
    setState(() {
      _isLoading = false;
    });
  }
Sign up to request clarification or add additional context in comments.

5 Comments

thank you for the input, but it did not worked., the issue persists. It calls the savePetData() twice.
where _handleSubmit is getting called?
it's called inside a FlatButton for OnPressed() which is inside a showModalBottomScheet. my intention is like this> user inputs register data for a pet. on save the modalBottomSheet will be called, then there are two options later and okay. in either of those two in flatButton onPressed() the _handleSubmit is called. on the success after submitting I need to close the modalBottomSheet and then navigate from that screen to the new one.
Check your setState calls, it looks unorganized. try setting breakpoints or take a boolean and check before calling savePetData, if it was called before to find out when it is getting called twice.
could you guide me in my code if it's not a trouble for you please ? much helpful

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.