I am trying to implement a simple news feed app using network call wherein the screen will show the latest stories in a Listview.
With the current code, I am getting a response back from the API (as I see the entire response body in the log) but can't seem to display the data in the UI. I am getting this error :
type _InternalLinkedHashMap<String, dynamic> is not subtype of type List
This is the JSON structure
{
"response": {
"status": "ok",
"userTier": "developer",
"total": 25095,
"startIndex": 1,
"pageSize": 10,
"currentPage": 1,
"pages": 2510,
"orderBy": "relevance",
"results": [
{
"id": "australia-news/2018/aug/13/turnbulls-energy-policy-hangs-in-the-balance-as-euthanasia-debate-given-precedence",
"type": "article",
"sectionId": "australia-news",
"sectionName": "Australia news",
"webPublicationDate": "2018-08-12T18:00:08Z",
"webTitle": "Energy policy hangs in balance, as Senate debates euthanasia",
"webUrl": "https://www.theguardian.com/australia-news/2018/aug/13/turnbulls-energy-policy-hangs-in-the-balance-as-euthanasia-debate-given-precedence",
"apiUrl": "https://content.guardianapis.com/australia-news/2018/aug/13/turnbulls-energy-policy-hangs-in-the-balance-as-euthanasia-debate-given-precedence",
"isHosted": false,
"pillarId": "pillar/news",
"pillarName": "News"
}, {
"id": "media/2018/jun/13/the-rev-colin-morris-obituary-letter",
"type": "article",
"sectionId": "media",
For my understanding, I just want to first display webTitle
in the list, and later add other fields (after I understand the network concept clearly), but getting the error mentioned above. This is my complete code :
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Network Example',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: AppBar(
title: new Text('Network Example'),
),
body: new Container(
child: new FutureBuilder<List<News>> (
future: fetchNews(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return new ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(snapshot.data[index].newsTitle,
style: new TextStyle(
fontWeight: FontWeight.bold)
),
new Divider()
],
);
}
);
} else if (snapshot.hasError) {
return new Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
),
),
);
}
Future<List<News>> fetchNews() async {
final response = await http.get('https://content.guardianapis.com/search?q=debates&api-key=');
print(response.body);
List responseJson = json.decode(response.body.toString());
List<News> newsTitle = createNewsList(responseJson);
return newsTitle;
}
List<News> createNewsList(List data) {
List<News> list = new List();
for (int i = 0; i< data.length; i++) {
String title = data[i]['webTitle'];
News news = new News(
newsTitle: title);
list.add(news);
}
return list;
}
}
class News {
final String newsTitle;
News({this.newsTitle});
factory News.fromJson(Map<String, dynamic> json) {
return new News(
newsTitle: json['webTitle'],
);
}
}
I looked at similar questions before and also went through json structures articles but can't seem to figure out how to resolve this issue.
The problem is, your JSON is not an array. It is an object. But you tried to use it as an array.
You may want to change your createNewsList
call to the following:
List responseJson = json.decode(response.body.toString());
List<News> newsTitle = createNewsList(responseJson["response"]["results"]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With