Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Error: type 'List<dynamic>' is not a subtype of type 'String' in Flutter

I’m learning to fetch a data from an API using mockapi.

I followed the flutter examples using the HTTP package but there’s something wrong with the code and I can’t seem to figure it out.

I have tried several APIs the one with headers and the one without it.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

store_groceries_api.dart

class Groceries {
  final int id;
  final String name;
  final String images;

  const Groceries({required this.id, required this.name, required this.images});

  factory Groceries.fromJson(Map<String, dynamic> json) {
    return Groceries(
        id: json['id'], name: json['name'], images: json['images']);
  }
}

Future<Groceries> fetchGroceries() async {
  final response = await http.get(Uri.parse(
      'https://6453dd71e9ac46cedf31d94e.mockapi.io/api/v1/groceries'));

  if (response.statusCode == 200) {
    final responseJson = jsonDecode(response.body);

    return Groceries.fromJson(responseJson);

  } else {
    throw Exception("Failed to load groceries");
  }
}

explore_screen.dart


class ExplorePage extends StatefulWidget {
  const ExplorePage({Key? key}) : super(key: key);

  @override
  _ExplorePageState createState() => _ExplorePageState();
}

class _ExplorePageState extends State<ExplorePage>
    with AutomaticKeepAliveClientMixin {
  late Future<Groceries> futureGroceries;
  @override
  void initState() {
    super.initState();
    futureGroceries = fetchGroceries();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      body: ListView(
        children: [
          CarouselSlider(
            items: const [
              Padding(
                padding: EdgeInsets.all(20.0),
                child: Text('Placeholder'),
              ),
              Padding(
                padding: EdgeInsets.all(20.0),
                child: Text('Placeholder'),
              ),
              Padding(
                padding: EdgeInsets.all(20.0),
                child: Text('Placeholder'),
              ),
              Padding(
                padding: EdgeInsets.all(20.0),
                child: Text('Placeholder'),
              )
            ],
            options: CarouselOptions(
              autoPlay: true,
            ),
          ),
          FutureBuilder<Groceries>(
            future: futureGroceries,
            builder: (context, AsyncSnapshot snapshot) {
              if (snapshot.hasData) {
                ListView.builder(
                    padding: const EdgeInsets.all(10),
                    itemCount: 4,
                    itemBuilder: (context, index) {
                      return ListTile(
                        title: Text(snapshot.data!.name),
                      );
                    });
              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }

              return const CircularProgressIndicator();
            },
          )
        ],
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

The data im trying to read

[
 {
  "name": "name 1",
  "images": "images 1",
  "id": "1"
 },
 {
  "name": "name 2",
  "images": "images 2",
  "id": "2"
 },
 {
  "name": "name 3",
  "images": "images 3",
  "id": "3"
 },
 {
  "name": "name 4",
  "images": "images 4",
  "id": "4"
 }
]

Sorry if the codes are poorly made.
As you can probably realize the if statement in the explore_screen.dart returned an error but the response status is 200

if (snapshot.hasData) {
  ListView.builder(
      padding: const EdgeInsets.all(10),
      itemCount: 4,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(snapshot.data!.name),
        );
      });
} else if (snapshot.hasError) {
  return Text('${snapshot.error}');
}

A help would be appreciated

>Solution :

You are getting list of items from api, it will be

Future<List<Groceries>> fetchGroceries() async {
  .....
  if (response.statusCode == 200) {
    final responseJson = jsonDecode(response.body);
    return List.from(responseJson).map((e) => Groceries.fromJson(e)).toList();
  } else {
    throw Exception("Failed to load groceries");
  }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading