in my flutter app I'm using API request from server with http get method. but the response is returning null while printing the data inside the request it has data. how can I make an API call the right way?
JSON data
{
"client": [
{
"id": 1,
"name": "Muhammed",
"address": "Mexico",
"tin_no": "123456789",
"status": "1",
"created_at": "2022-09-09T08:44:18.000000Z",
"updated_at": "2022-09-09T08:44:18.000000Z",
"phones": [
{
"id": 2,
"client_id": "1",
"supplier_id": null,
"company_id": null,
"phone_number": "0911112222",
"email": "[email protected]",
"model": "Client",
"category": null,
"created_at": "2022-09-09T08:44:18.000000Z",
"updated_at": "2022-09-09T08:44:18.000000Z"
}
]
},
{
"id": 2,
"name": "Salem",
"address": "Torhailouch",
"tin_no": "87654321",
"status": "1",
"created_at": "2022-09-10T05:54:47.000000Z",
"updated_at": "2022-09-10T05:54:47.000000Z",
"phones": [
{
"id": 3,
"client_id": "2",
"supplier_id": null,
"company_id": null,
"phone_number": "0944551122",
"email": "[email protected]",
"model": "Client",
"category": "Sales",
"created_at": "2022-09-10T05:54:47.000000Z",
"updated_at": "2022-09-10T05:54:47.000000Z"
}
]
},]
}
Client model
class Client {
List<Clients>? clients;
Client({required this.clients});
Client.fromJson(Map<String, dynamic> json) {
if (json['clients'] != null) {
clients = <Clients>[];
json['clients'].forEach((v) {
clients?.add(new Clients.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.clients != null) {
data['clients'] = this.clients!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Clients {
int? id;
String? name;
String? address;
String? tinNo;
String? status;
String? createdAt;
String? updatedAt;
List<Phones>? phones;
Clients(
{this.id,
this.name,
this.address,
this.tinNo,
this.status,
this.createdAt,
this.updatedAt,
this.phones});
Clients.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
address = json['address'];
tinNo = json['tin_no'];
status = json['status'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
if (json['phones'] != null) {
phones = <Phones>[];
json['phones'].forEach((v) {
phones!.add(new Phones.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['address'] = this.address;
data['tin_no'] = this.tinNo;
data['status'] = this.status;
data['created_at'] = this.createdAt;
data['updated_at'] = this.updatedAt;
if (this.phones != null) {
data['phones'] = this.phones!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Phones {
int? id;
String? clientId;
Null? supplierId;
Null? companyId;
String? phoneNumber;
String? email;
String? model;
String? category;
String? createdAt;
String? updatedAt;
Phones(
{this.id,
this.clientId,
this.supplierId,
this.companyId,
this.phoneNumber,
this.email,
this.model,
this.category,
this.createdAt,
this.updatedAt});
Phones.fromJson(Map<String, dynamic> json) {
id = json['id'];
clientId = json['client_id'];
supplierId = json['supplier_id'];
companyId = json['company_id'];
phoneNumber = json['phone_number'];
email = json['email'];
model = json['model'];
category = json['category'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['client_id'] = this.clientId;
data['supplier_id'] = this.supplierId;
data['company_id'] = this.companyId;
data['phone_number'] = this.phoneNumber;
data['email'] = this.email;
data['model'] = this.model;
data['category'] = this.category;
data['created_at'] = this.createdAt;
data['updated_at'] = this.updatedAt;
return data;
}
}
API call is as follows
Future<List<Client>> fetchClient() async {
Uri url = Uri.parse("${BASE_URL}client");
var response = await http.get(url, headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer $TOKEN',
});
var data = json.decode(response.body);
print('...................$data...................');
List<Client> clients = [];
if (response.statusCode == 200) {
for (var singleClient in data) {
Client client = Client(clients: singleClient['clients']);
clients.add(client);
}
}
return clients;
}
main page
return FutureBuilder<List<Client>>(
future: fetchClient(),
builder: (context, AsyncSnapshot snapshot) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Text(index.toString());
});
});
Error thrown for this
Another exception was thrown: NoSuchMethodError: The getter 'length' was called on null.
what is the problem and how can I solve this?
CodePudding user response:
Change your fetchClient()
to this:
Future<List<Clients>> fetchClient() async {
Uri url = Uri.parse("${BASE_URL}client");
var response = await http.get(url, headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Bearer $TOKEN',
});
var data = json.decode(response.body);
print('...................$data...................');
List<Clients> clients = [];
if (response.statusCode == 200) {
for (var singleClient in data["client"]) {
clients.add(Clients.fromJson(singleClient));
}
}
return clients;
}
and also in your FutureBuilder
do this:
return FutureBuilder<List<Clients>>(
future: fetchClient(),
builder: (context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return const CircularProgressIndicator();
default:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
List<Clients> data = snapshot.data;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return Text(data[index].name);
});
});
}
}
});
CodePudding user response:
You need to check in your builder whether the data is finished loading. something like
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Text(index.toString());
});
} else {
return const CircularProgressIndicator();
}