Flutter StreamProvider 'List<dynamic>' is not a subtype of type 'List<??>' in type cast

Issue

I’m trying to user StreamProvider to make data from a firestore doc stream available throughout my app. Its a recipe app and this is the shopping list.

I have a model RecipeItem that contains details about the item from the recipe. The firestore doc holds one value which is an array, called ‘list’, containing maps for each item that is in the list.

Below is my connection to firestore and setting up the stream. I try to get the doc, then user map to create a RecipeItem instance for each item in the list. Here is the method:

Stream<List<RecipeItem>> getPersonalList() {
    print('Fetching personal list');

    return _db.collection('shopping_lists').document(userId).snapshots().map(
          (DocumentSnapshot documentSnapshot) => documentSnapshot.data['list']
              .map(
                (item) =>
                    // print(item);
                    RecipeItem(
                  category: item['category'],
                  wholeLine: item['wholeLine'],
                  recipeTitle: item['recipeTitle'],
                  recipeId: item['recipeId'],
                  purchased: item['purchased'],
                ),
              )
              .toList(),
        );
  }

Now in main.dart I have a StreamProvider that looks for type <List<RecipeItem>>

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        StreamProvider<FirebaseUser>(
            //Access withing the app -> var user = Provider.of<FirebaseUser>(context);
            create: (_) => AuthService().user),
        StreamProvider<List<RecipeItem>>(
          create: (_) => PersonalListDB().getPersonalList(),
          catchError: (context, error) {
            print('This is the error from stream provider *** $error');
          },
        ),
        ChangeNotifierProvider(
          create: (_) => RecipesDB(),
        )
      ],
      child: MaterialApp(
etc etc...

When I run this I get this error:

type ‘List’ is not a subtype of type ‘List’ in type cast

The only way I can fix this is if I change everywhere I have List<RecipeItem> to List<dynamic>. This works but it doesn’t seem like the right solution.

I have tried a few (a million) things.

I found this post here: Getting type 'List<dynamic>' is not a subtype of type 'List<…>' error in JSON

This tells me that .toList() might be the problem because it creates List. So I have tried using List.from and using .cast<List> but have had no luck. What is further confusing me is that I pretty closely follow other tutorials doing similar things.

Any help to resolve this and help me understand the problem is greatly appreciated.

Solution

The List of Firestore (db, httpRequest, etc) are of type dynamic to avoid problems when calling them, you can try to tell the map of what type are you trying to cast your object

return _db.collection('shopping_lists').document(userId).snapshots().map<List<RecipeItem>>( //I'm not sure what kind of object this map should return, is this the method map part of the stream? if it is then it should be of type List<RecipeItem>
      (DocumentSnapshot documentSnapshot) => documentSnapshot.data['list']
          .map<RecipeItem>( //now it will know it's not a dynamic value but of type RecipeItem
            (item) =>
                // print(item);
                RecipeItem(
              category: item['category'],
              wholeLine: item['wholeLine'],
              recipeTitle: item['recipeTitle'],
              recipeId: item['recipeId'],
              purchased: item['purchased'],
            ),
          )
          .toList(),
);

Answered By – EdwynZN

Answer Checked By – Mary Flores (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *