Search code examples
flutterdartriverpod

type'_Map<String, dynamic>' is not a subtype of type 'List<dynamic>'


Hello.. i am sending a get request with http package and trying to display the data from a future provider using the .when() function. Ive done everything but it keeps giving me this error without pointing me to where the error is from please help.

this is my http request.

import 'dart:convert';

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:friendnpal/models/articles_model.dart';
import 'package:http/http.dart';

class ApiServices {
  String endpoint =
      'https://friendnpalapp-production-0d46.up.railway.app/api/article/random_daily';
  Future<List<ArticlesModel>> getArticles() async {
    Response response = await get(Uri.parse(endpoint));

    if (response.statusCode == 200) {
      final List result = jsonDecode(response.body);
      print(response.body);
      return result.map(((e) => ArticlesModel.fromJson(e))).toList();
    } else {
      print('error');
      throw Exception(response.reasonPhrase);
    }
  }
}
`
final articlesProvider = Provider<ApiServices>((ref) => ApiServices());`

this is where is use the data

`import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';`
import 'package:friendnpal/models/articles_model.dart';
import '../../../data_provider.dart';
import '../../../in_app_browser/in_app_browser_screen.dart';
import '../../../utils/app_colors.dart';
import '../../../utils/app_strings.dart';

class ArticlesWidget extends ConsumerWidget {
  const ArticlesWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final _data = ref.watch(articlesDataProvider);

    return _data.when(
        data: (_data) {
          List<ArticlesModel> articlesList = _data.map((e) => e).toList();

          return ListView.builder(
            itemCount: articlesList.length,
            itemBuilder: (context, index) {
              return Container(
                padding: const EdgeInsets.fromLTRB(18, 19, 18, 7),
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(12),
                  gradient: const LinearGradient(
                    colors: [
                      Color(0xff5F7AFF),
                      Color(0xff04D486),
                    ],
                  ),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Container(
                      margin: const EdgeInsets.only(bottom: 24),
                      alignment: Alignment.center,
                      child: const Text(
                        'Article of the day',
                        style: TextStyle(
                            fontSize: 20,
                            color: AppColors.white,
                            fontFamily: AppStrings.fontName),
                      ),
                    ),
                    Text(
                      articlesList[index].content!,
                      textAlign: TextAlign.center,
                      style: TextStyle(
                          fontSize: 16,
                          color: AppColors.white,
                          fontFamily: AppStrings.fontName),
                    ),
                    GestureDetector(
                      onTap: () {
                        Navigator.push(
                            context,

                            /// navigate to inAppBrowser
                            MaterialPageRoute(
                                builder: (context) => InAppBrowserPage(
                                      articlesList: articlesList[index],
                                    )));
                      },
                      child: Container(
                        padding: EdgeInsets.all(10),
                        margin: const EdgeInsets.only(top: 39),
                        decoration: BoxDecoration(
                            color: AppColors.blue,
                            borderRadius: BorderRadius.circular(72)),
                        child: const Text(
                          'Read More',
                          style: TextStyle(
                              fontSize: 15,
                              color: AppColors.white,
                              fontFamily: AppStrings.fontName),
                        ),
                      ),
                    )
                  ],
                ),
              );
            },
          );
        },
        error: (err, s) => Text(err.toString()),
        loading: () => Center(
              child: CircularProgressIndicator(),
            ));
  }
}

plese i need to know what caused the error also


Solution

  • It most likely goes wrong on

      final List result = jsonDecode(response.body);
    

    because the response is not a list.

    The error indicates that it is a map.

    In other words, your response.body is of the form

    {
      ...
    }
    

    and not

    [
      ...
    ]
    

    maybe in your case you have something like

    {
      "data" : [
        ...
      ]
    }
    

    In that case you need to replace the code to

      final List result = jsonDecode(response.body)['data'];
    

    EDIT:

    I just tried out the url and can see that this is the response

    {
      "_id": "647c410f5504275bc960719b",
      "articleID": "2",
      "title": "Mastering the Art of Time Managemen",
      "content": "Learn effective strategies and practical tips to manage your time efficiently. Boost your productivity, prioritize tasks, and strike a balance between work and personal life.",
      "link": "https://www.example.com/article1",
      "selectedDate": "2023-06-06T00:00:00.000Z",
      "selectedWeek": null,
      "__v": 0
    }
    

    As you can see this is a single article, but you are trying to parse it as if it's a list. The easiest fix would then be to wrap it in a list, like this for example:

      final List result = [jsonDecode(response.body)];