Tring to fetch data using API
My code
class _MyAppState extends State<MyApp> {
Future<News> news;
@override
void initState() {
super.initState();
news = fetchNews();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
debugShowCheckedModeBanner: false,
home:
Container(
color: Colors.white24,
child:
Center(child:
FutureBuilder<News>(
future: fetchNews(),
builder: (context, snapshot) {
if (snapshot.hasData) {
/* here if I removed toString() it gives me error
The argument type 'News' can't be assigned to the parameter type
'String'. */
return Text(snapshot.data.toString());
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
),
)
);
}
}
News newsFromJson(String str) => News.fromJson(json.decode(str));
String newsToJson(News data) => json.encode(data.toJson());
class News {
News({
this.status,
this.totalResults,
this.articles,
});
String status;
int totalResults;
List<Article> articles;
factory News.fromJson(Map<String, dynamic> json) => News(
status: json["status"],
totalResults: json["totalResults"],
articles: List<Article>.from(json["articles"].map((x) => Article.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"totalResults": totalResults,
"articles": List<dynamic>.from(articles.map((x) => x.toJson())),
};
}
class Article {
Article({
this.source,
this.author,
this.title,
this.description,
this.url,
this.urlToImage,
this.publishedAt,
this.content,
});
Source source;
String author;
String title;
String description;
String url;
String urlToImage;
DateTime publishedAt;
String content;
factory Article.fromJson(Map<String, dynamic> json) => Article(
source: Source.fromJson(json["source"]),
author: json["author"] == null ? null : json["author"],
title: json["title"],
description: json["description"] == null ? null : json["description"],
url: json["url"],
urlToImage: json["urlToImage"] == null ? null : json["urlToImage"],
publishedAt: DateTime.parse(json["publishedAt"]),
content: json["content"],
);
Map<String, dynamic> toJson() => {
"source": source.toJson(),
"author": author == null ? null : author,
"title": title,
"description": description == null ? null : description,
"url": url,
"urlToImage": urlToImage == null ? null : urlToImage,
"publishedAt": publishedAt.toIso8601String(),
"content": content,
};
}
class Source {
Source({
this.id,
this.name,
});
dynamic id;
String name;
factory Source.fromJson(Map<String, dynamic> json) => Source(
id: json["id"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
};
}
Future<News> fetchNews() async {
final response = await http.get('My-Api');
if (response.statusCode == 200) {
return News.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load album');
}
}
when I run this Code the output is : Instance of 'News'
I searched the internet and found most solutions saying I must add await.
The only problem is THEY DON'T SAY WHERE SHOULD I PUT IT EXACTLY IN THE CODE
Your help will be appreciated,
Thank you
Note: I'm still a beginner
You don't need to add await
. Your code is working correctly. The only thing I would change is
FutureBuilder<News>(
future: fetchNews(),
to
FutureBuilder<News>(
future: news,
Here is a very good explanation for this.
Your output Instance of 'News'
is correct. It's the model
you declared for the output of your network call. You now have access to it's properties (status
, totalResults
and articles
).
/* here if I removed toString() it gives me error The argument type 'News' can't be assigned to the parameter type 'String'. */
That's because the Text
widget expects his input to be of typ String
and not of type News
.