#flutter #api #dart #snapshot #flutter-futurebuilder
Вопрос:
Поэтому я пытаюсь получить данные из API и отобразить их в listview, но я вижу, что в журналах приходит ответ, но когда приходит снимок, в нем нет данных, и поэтому круговой индикатор продолжает вращаться. Не знаю, в чем ошибка. вот открытый API, который я использовал https://randomuser.me/api/?results=10
, я новичок в flutter, пожалуйста, кто-нибудь, помогите мне. Заранее спасибо.
главная.дротик
import 'package:flutter/material.dart';
import 'api_provider/api_services.dart';
import 'model/user_data/users_data_response.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "User List",
home: UsersDetails(title:"User List"),
);
}
}
class UsersDetails extends StatefulWidget {
const UsersDetails({Key? key,this.title}) : super(key: key);
final String? title;
@override
_UsersDetailsState createState() => _UsersDetailsState();
}
class _UsersDetailsState extends State<UsersDetails> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title!),
),
body: Container(
child: FutureBuilder<UsersData>(
future: fetchUsersData(),
builder: ( context,AsyncSnapshot snapshot){
if(snapshot.hasData){
return ListView.builder(
padding: EdgeInsets.all(8),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context,int index ){
return Card(
child: Column(
children: [
ListTile(
leading: CircleAvatar(
radius: 30.0,
backgroundImage: NetworkImage(snapshot.data[index]['picture']['large'])),
title: Text((snapshot.data[index]['name']['first'])),
subtitle: Text((snapshot.data[index]['location']['city'])),
trailing: Text((snapshot.data[index]['dob']['age'])),
),
],
),
);
}
);
}
else{
return Center(child: CircularProgressIndicator());
}
}
),
),
);
}
}
user_data_response.dart
import 'dart:convert';
UsersData usersDataFromJson(String str) => UsersData.fromJson(json.decode(str));
String usersDataToJson(UsersData data) => json.encode(data.toJson());
class UsersData {
UsersData({
this.results,
this.info,
});
List<Result>? results;
Info? info;
factory UsersData.fromJson(Map<String, dynamic> json) => UsersData(
results: json["results"] == null ? null : List<Result>.from(json["results"].map((x) => Result.fromJson(x))),
info: json["info"] == null ? null : Info.fromJson(json["info"]),
);
Map<String, dynamic> toJson() => {
"results": results == null ? null : List<dynamic>.from(results!.map((x) => x.toJson())),
"info": info == null ? null : info!.toJson(),
};
}
class Info {
Info({
this.seed,
this.results,
this.page,
this.version,
});
String? seed;
int? results;
int? page;
String? version;
factory Info.fromJson(Map<String, dynamic> json) => Info(
seed: json["seed"] == null ? null : json["seed"],
results: json["results"] == null ? null : json["results"],
page: json["page"] == null ? null : json["page"],
version: json["version"] == null ? null : json["version"],
);
Map<String, dynamic> toJson() => {
"seed": seed == null ? null : seed,
"results": results == null ? null : results,
"page": page == null ? null : page,
"version": version == null ? null : version,
};
}
class Result {
Result({
this.gender,
this.name,
this.location,
this.email,
this.login,
this.dob,
this.registered,
this.phone,
this.cell,
this.id,
this.picture,
this.nat,
});
Gender? gender;
Name? name;
Location? location;
String? email;
Login? login;
Dob? dob;
Dob? registered;
String? phone;
String? cell;
Id? id;
Picture? picture;
String? nat;
factory Result.fromJson(Map<String, dynamic> json) => Result(
gender: json["gender"] == null ? null : genderValues.map![json["gender"]],
name: json["name"] == null ? null : Name.fromJson(json["name"]),
location: json["location"] == null ? null : Location.fromJson(json["location"]),
email: json["email"] == null ? null : json["email"],
login: json["login"] == null ? null : Login.fromJson(json["login"]),
dob: json["dob"] == null ? null : Dob.fromJson(json["dob"]),
registered: json["registered"] == null ? null : Dob.fromJson(json["registered"]),
phone: json["phone"] == null ? null : json["phone"],
cell: json["cell"] == null ? null : json["cell"],
id: json["id"] == null ? null : Id.fromJson(json["id"]),
picture: json["picture"] == null ? null : Picture.fromJson(json["picture"]),
nat: json["nat"] == null ? null : json["nat"],
);
Map<String, dynamic> toJson() => {
"gender": gender == null ? null : genderValues.reverse![gender],
"name": name == null ? null : name!.toJson(),
"location": location == null ? null : location!.toJson(),
"email": email == null ? null : email,
"login": login == null ? null : login!.toJson(),
"dob": dob == null ? null : dob!.toJson(),
"registered": registered == null ? null : registered!.toJson(),
"phone": phone == null ? null : phone,
"cell": cell == null ? null : cell,
"id": id == null ? null : id!.toJson(),
"picture": picture == null ? null : picture!.toJson(),
"nat": nat == null ? null : nat,
};
}
class Dob {
Dob({
this.date,
this.age,
});
DateTime? date;
int? age;
factory Dob.fromJson(Map<String, dynamic> json) => Dob(
date: json["date"] == null ? null : DateTime.parse(json["date"]),
age: json["age"] == null ? null : json["age"],
);
Map<String, dynamic> toJson() => {
"date": date == null ? null : date!.toIso8601String(),
"age": age == null ? null : age,
};
}
enum Gender { FEMALE, MALE }
final genderValues = EnumValues({
"female": Gender.FEMALE,
"male": Gender.MALE
});
class Id {
Id({
this.name,
this.value,
});
String? name;
String? value;
factory Id.fromJson(Map<String, dynamic> json) => Id(
name: json["name"] == null ? null : json["name"],
value: json["value"] == null ? null : json["value"],
);
Map<String, dynamic> toJson() => {
"name": name == null ? null : name,
"value": value == null ? null : value,
};
}
class Location {
Location({
this.street,
this.city,
this.state,
this.country,
this.postcode,
this.coordinates,
this.timezone,
});
Street? street;
String? city;
String? state;
String? country;
dynamic postcode;
Coordinates? coordinates;
Timezone? timezone;
factory Location.fromJson(Map<String, dynamic> json) => Location(
street: json["street"] == null ? null : Street.fromJson(json["street"]),
city: json["city"] == null ? null : json["city"],
state: json["state"] == null ? null : json["state"],
country: json["country"] == null ? null : json["country"],
postcode: json["postcode"],
coordinates: json["coordinates"] == null ? null : Coordinates.fromJson(json["coordinates"]),
timezone: json["timezone"] == null ? null : Timezone.fromJson(json["timezone"]),
);
Map<String, dynamic> toJson() => {
"street": street == null ? null : street!.toJson(),
"city": city == null ? null : city,
"state": state == null ? null : state,
"country": country == null ? null : country,
"postcode": postcode,
"coordinates": coordinates == null ? null : coordinates!.toJson(),
"timezone": timezone == null ? null : timezone!.toJson(),
};
}
class Coordinates {
Coordinates({
this.latitude,
this.longitude,
});
String? latitude;
String? longitude;
factory Coordinates.fromJson(Map<String, dynamic> json) => Coordinates(
latitude: json["latitude"] == null ? null : json["latitude"],
longitude: json["longitude"] == null ? null : json["longitude"],
);
Map<String, dynamic> toJson() => {
"latitude": latitude == null ? null : latitude,
"longitude": longitude == null ? null : longitude,
};
}
class Street {
Street({
this.number,
this.name,
});
int? number;
String? name;
factory Street.fromJson(Map<String, dynamic> json) => Street(
number: json["number"] == null ? null : json["number"],
name: json["name"] == null ? null : json["name"],
);
Map<String, dynamic> toJson() => {
"number": number == null ? null : number,
"name": name == null ? null : name,
};
}
class Timezone {
Timezone({
this.offset,
this.description,
});
String? offset;
String? description;
factory Timezone.fromJson(Map<String, dynamic> json) => Timezone(
offset: json["offset"] == null ? null : json["offset"],
description: json["description"] == null ? null : json["description"],
);
Map<String, dynamic> toJson() => {
"offset": offset == null ? null : offset,
"description": description == null ? null : description,
};
}
class Login {
Login({
this.uuid,
this.username,
this.password,
this.salt,
this.md5,
this.sha1,
this.sha256,
});
String? uuid;
String? username;
String? password;
String? sa<
String? md5;
String? sha1;
String? sha256;
factory Login.fromJson(Map<String, dynamic> json) => Login(
uuid: json["uuid"] == null ? null : json["uuid"],
username: json["username"] == null ? null : json["username"],
password: json["password"] == null ? null : json["password"],
salt: json["salt"] == null ? null : json["salt"],
md5: json["md5"] == null ? null : json["md5"],
sha1: json["sha1"] == null ? null : json["sha1"],
sha256: json["sha256"] == null ? null : json["sha256"],
);
Map<String, dynamic> toJson() => {
"uuid": uuid == null ? null : uuid,
"username": username == null ? null : username,
"password": password == null ? null : password,
"salt": salt == null ? null : salt,
"md5": md5 == null ? null : md5,
"sha1": sha1 == null ? null : sha1,
"sha256": sha256 == null ? null : sha256,
};
}
class Name {
Name({
this.title,
this.first,
this.last,
});
Title? title;
String? first;
String? last;
factory Name.fromJson(Map<String, dynamic> json) => Name(
title: json["title"] == null ? null : titleValues.map![json["title"]],
first: json["first"] == null ? null : json["first"],
last: json["last"] == null ? null : json["last"],
);
Map<String, dynamic> toJson() => {
"title": title == null ? null : titleValues.reverse![title],
"first": first == null ? null : first,
"last": last == null ? null : last,
};
}
enum Title { MS, MR, MRS }
final titleValues = EnumValues({
"Mr": Title.MR,
"Mrs": Title.MRS,
"Ms": Title.MS
});
class Picture {
Picture({
this.large,
this.medium,
this.thumbnail,
});
String? large;
String? medium;
String? thumbnail;
factory Picture.fromJson(Map<String, dynamic> json) => Picture(
large: json["large"] == null ? null : json["large"],
medium: json["medium"] == null ? null : json["medium"],
thumbnail: json["thumbnail"] == null ? null : json["thumbnail"],
);
Map<String, dynamic> toJson() => {
"large": large == null ? null : large,
"medium": medium == null ? null : medium,
"thumbnail": thumbnail == null ? null : thumbnail,
};
}
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_services.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:api_usage/model/user_data/users_data_response.dart';
final String api ="https://randomuser.me/api/?results=";
int userCount=10;
Future<UsersData> fetchUsersData() async {
final request=api userCount.toString();
final response = await http.get(Uri.parse(request));
if (response.statusCode == 200) {
final result = json.decode(response.body);
debugPrint("result-----${result}");
return result['results'];
}
else {
throw Exception('Failed to load UsersData');
}
}
Ответ №1:
Это происходит из-за того, что вы не учитываете ошибку в моментальном снимке. Все, что не является snapshot.hasData, вызывает срабатывание счетчика в вашем случае прямо сейчас. Добавьте еще один тест для if (snapshot.hasError) и правильно обработайте его, это должно вывести вас на правильный путь. Подсказка: вы не возвращаете данные пользователей, как было обещано в FutureBuilder.
UPD:
Также имейте в виду, что из-за особенностей работы виджетов FutureBuilder может быть перестроен, что приведет к многократному вызову функции выборки. Возможно, вы захотите избежать этого.
UPD 2:
Чтобы расширить то, что я сказал выше. В вашем FutureBuilder вы только проверяете, есть ли у snapshot.hasData, и в ЛЮБОМ другом случае вы показываете индикатор, который указывает как на (1) моментальный снимок без каких-либо данных, так и на (2) снимок с ошибкой.
Попробуйте добавить другое условие if, чтобы перехватить и обработать ошибку, вот так:
if (snapshot.hasData) {
return ...
} else if (snapshot.hasError) {
return ...
} else {
return Center(child: CircularProgressIndicator());
}
Этого второго условия должно быть достаточно, чтобы продвинуть вас вперед с кодом.
Комментарии:
1. Спасибо @jabbson,но я не совсем понял это, и я немного новичок в flutter, не могли бы вы, пожалуйста, отредактировать код, в котором я допустил ошибку, чтобы я мог понять это и был полезен для меня 😃
2. Добавлено еще одно обновление к ответу, извините, если я сначала не понял свое объяснение.