I am having trouble trying to iterate over a JSON array of objects from a remote URL using Flutter's FutureBuilder.
My goal is to:
The JSON data is an array of objects(or a List of Maps in dart), the objects have simple string data.
I know that I need to build a future to fetch the data from the API and decode the JSON, then I need to create a FutureBuilder to output the List data into my Gridview Builder. That is what I have tried to do in my code below.
import 'dart:convert';
import 'dart:async';
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class HomeSection extends StatefulWidget {
@override
_HomeSectionState createState() => _HomeSectionState();
}
class _HomeSectionState extends State<HomeSection> {
@override
void initState() {
super.initState();
}
Future<List<dynamic>> fetchSectionData() async {
String dataUrl =
'https://www.thisisthejsonapilink.co.uk/fetch-data';
var response = await http.get(Uri.parse(dataUrl));
if (response.statusCode == 200) {
return jsonDecode(response.body);
} else {
throw Exception('Failed to get the data');
}
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: fetchSectionData,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return GridView.builder(
itemCount: 12,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 300,
crossAxisSpacing: 16.0,
mainAxisSpacing: 18.0,
childAspectRatio: MediaQuery.of(context).size.height / 930,
),
itemBuilder: (BuildContext context, int index) => GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => OtherScreen()),
);
},
child: Column(
children: [
Container(
margin: const EdgeInsets.only(bottom: 12.0),
height: 144,
),
Text(
snapshot.data[index].title,
),
Text(
snapshot.data[index].duration + ' - ' + snapshot.data[index].type,
),
],
),
),
);
} else {
return Center(
child: CircularProgressIndicator(
color: Colors.black,
),
);
}
},
);
}
}
My JSON that returns from the API link is structured like this:
[
{
"Title": "Audio 1",
"Duration": "5 min",
"type": "audio",
"bodyText": "lorem ipsum blah blah audio",
"url": "https://www.silvermansound.com/music/dirty-gertie.mp3"
},
{
"Title": "Video 1",
"Duration": "5 min",
"type": "video",
"bodyText": "lorem ipsum blah blah video",
"url": "https://assets.mixkit.co/videos/preview/mixkit-woman-wearing-a-mask-while-running-40158-large.mp4"
},
{
"Title": "Audio 2",
"Duration": "5 min",
"type": "audio",
"bodyText": "lorem ipsum blah blah audio",
"url": "https://www.silvermansound.com/music/dirty-gertie.mp3"
},
{
"Title": "Video 2",
"Duration": "5 min",
"type": "video",
"bodyText": "lorem ipsum blah blah video",
"url": "https://assets.mixkit.co/videos/preview/mixkit-woman-wearing-a-mask-while-running-40158-large.mp4"
},
{
"Title": "Audio 3",
"Duration": "5 min",
"type": "audio",
"bodyText": "lorem ipsum blah blah audio",
"url": "https://www.silvermansound.com/music/dirty-gertie.mp3"
},
{
"Title": "Video 3",
"Duration": "5 min",
"type": "video",
"bodyText": "lorem ipsum blah blah video",
"url": "https://assets.mixkit.co/videos/preview/mixkit-woman-wearing-a-mask-while-running-40158-large.mp4"
},
]
This is the error I am getting in my VS code debug console:
The argument type 'Future<List<dynamic>> Function()' can't be assigned to the parameter type 'Future<Object?>?'.
The red line appears right where I try to define my future in the FutureBuilder here under fetchSectionData
:
return FutureBuilder(
future: fetchSectionData,
builder: (context, snapshot) {
I am not sure what this error means. Could somebody please explain it? The Future is definitely returning a <List>, but how do I get this list into the futurebuilder so that I can iterate over it and output the data into the gridview?
I am fairly new to flutter and come from a javascript web background, usually in javascript you can just loop over an array and output it that way. I'm tempted to do it that way here but I know that wouldn't be right.
When I looked up the Flutter documentation on how to fetch data from the internet it mentioned that I have to convert the response into a custom dart object, but nothing I try seems to work.
Appreciate your help!
Try this !
return FutureBuilder<List<dynamic>>(
future: fetchSectionData,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return GridView.builder(
itemCount: 12,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 300,
crossAxisSpacing: 16.0,
mainAxisSpacing: 18.0,
childAspectRatio: MediaQuery.of(context).size.height / 930,
),
itemBuilder: (BuildContext context, int index) => GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => OtherScreen()),
);
},
child: Column(
children: [
Container(
margin: const EdgeInsets.only(bottom: 12.0),
height: 144,
),
Text(
'${snapshot.data[index]['Title']}',
),
Text(
'${snapshot.data[index]['Duration'] + ' - ' + snapshot.data[index]['type']}',
),
],
),
),
);
} else {
return Center(
child: CircularProgressIndicator(
color: Colors.black,
),
);
}
},
);