REST GET is returning invalid arguments in Future Builder

203 Views Asked by At

I'm using a Rest API to call a GET method to fetch some Data. I'm doing this to load a profile to view inside my flutter body. I'm trying to assign these data to String variables inside the FutureBuilder method . In the future builder , the fetchUser() API call response should be returning, but the snapshot returns a null. and so when ever I try to run this, the screen is stuck in the CircularProgressIndicator. can someone help me to figure this out where I'm doing this wrong and how to solve it?

The body in flutter page

final userProfileView = FutureBuilder<UserFetch>(
        future: CallApi().fetchUser(apiUrl),
        builder: (context, snapshot) {
          if(!snapshot.hasData)//(!snapshot.hasData)
            return Center(
              widthFactor: 120.0,
              heightFactor: 120.0,
              child: CircularProgressIndicator(),
            );
            // final userD = snapshot.data;
            _userName = snapshot.data.user.username.toString();
            _userEmail = snapshot.data.user.email;
            _userAddress = snapshot.data.user.address.toString();
            _userPassword = 'password';
            _userCountry = 'country';
            _userMobile = snapshot.data.user.mobile.toString();
            //checks if the response returns valid data
            return Container(
              child: Padding(
                padding:
                    const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
                child: SingleChildScrollView(
                  child: Column(
                    children: <Widget>[
                      userTitle,
                      SizedBox(height: 12.0),
                      userNameTitle,
                      userName,
                      SizedBox(height: 12.0),
                      userEmailTitle,
                      userEmail,
                      SizedBox(height: 12.0),
                      userPasswordTitle,
                      userPassword,
                      SizedBox(height: 12.0),
                      userAddressTitle,
                      userAddress,
                      SizedBox(height: 12.0),
                      userCountryTitle,
                      userCountry,
                      SizedBox(height: 12.0),
                      userPhoneTitle,
                      userPhone,
                      SizedBox(height: 24.0),
                      userLogoutBtn,
                    ],
                  ),
                ),
              ),
            );
          // } else if (snapshot.hasError) {
          //   //checks if the response throws an error
          //   return Text("${snapshot.error}");
          // }
        });

The Api Call

Future<UserFetch> fetchUser(apiUrl) async {
    var fullUrl = _baseUrl + apiUrl;
    final response = await http.get(fullUrl, headers: _setHeaders());

    if (response.statusCode == 200) {
      // If the call to the server was successful (returns OK), parse the JSON.
      return UserFetch.fromJson(json.decode(response.body));
    } else {
      // If that call was not successful (response was unexpected), it throw an error.
      throw Exception('Failed to load User');
    }
  }

The Response Model

UserFetch userFetchFromJson(String str) => UserFetch.fromJson(json.decode(str));

String userFetchToJson(UserFetch data) => json.encode(data.toJson());

class UserFetch {
  UserFetch({
    this.success,
    this.user,
  });

  bool success;
  User user;

  factory UserFetch.fromJson(Map<String, dynamic> json) => UserFetch(
    success: json["success"],
    user: User.fromJson(json["user"]),
  );

  Map<String, dynamic> toJson() => {
    "success": success,
    "user": user.toJson(),
  };
}

class User {
  User({
    this.email,
    this.address,
    this.imperial,
    this.mobile,
    this.petsInfo,
    this.role,
    this.subscribed,
    this.username,
  });

  String email;
  String address;
  bool imperial;
  String mobile;
  List<PetsInfo> petsInfo;
  String role;
  bool subscribed;
  String username;

  factory User.fromJson(Map<String, dynamic> json) => User(
    email: json["email"],
    address: json["address"],
    imperial: json["imperial"],
    mobile: json["mobile"],
    petsInfo: List<PetsInfo>.from(json["pets_info"].map((x) => PetsInfo.fromJson(x))),
    role: json["role"],
    subscribed: json["subscribed"],
    username: json["username"],
  );

  Map<String, dynamic> toJson() => {
    "email": email,
    "address": address,
    "imperial": imperial,
    "mobile": mobile,
    "pets_info": List<dynamic>.from(petsInfo.map((x) => x.toJson())),
    "role": role,
    "subscribed": subscribed,
    "username": username,
  };
}

class PetsInfo {
  PetsInfo({
    this.id,
    this.name,
  });

  int id;
  String name;

  factory PetsInfo.fromJson(Map<String, dynamic> json) => PetsInfo(
    id: json["id"],
    name: json["name"],
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "name": name,
  };
}

The Logs when user profile page called


════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
'package:flutter/src/widgets/framework.dart': Failed assertion: line 273 pos 18: '_registry.containsKey(key)': is not true.
════════════════════════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
'package:flutter/src/widgets/framework.dart': Failed assertion: line 273 pos 18: '_registry.containsKey(key)': is not true.


Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=BUG.md

When the exception was thrown, this was the stack: 
#2      GlobalKey._debugVerifyIllFatedPopulation.<anonymous closure> (package:flutter/src/widgets/framework.dart:273:18)
#3      GlobalKey._debugVerifyIllFatedPopulation (package:flutter/src/widgets/framework.dart:298:6)
#4      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2769:21)
#5      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2849:8)
#6      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:915:18)

1

There are 1 best solutions below

6
On

use future type to API call function because it is not decided that what is coming in future like this

Future<dymamic> fetchUser(apiUrl) async {
    var fullUrl = _baseUrl + apiUrl;
    final response = await http.get(fullUrl, headers: _setHeaders());

    if (response.statusCode == 200) {
      // If the call to the server was successful (returns OK), parse the JSON.
      return UserFetch.fromJson(json.decode(response.body));
    } else {
      // If that call was not successful (response was unexpected), it throw an error.
      throw Exception('Failed to load User');
    }
  }

now check the response in FutureBuiler whether it throws an error or not.

if(snapshot.data=="Failed to load User"){
   return Text("something went wrong");
}