Search code examples
flutterdartgoogle-cloud-firestorelisttile

An exception was throw by _MapStream<QuerySnapshot<Map<String, dynamic>>, List<Stuff>> listened by


I was trying to list some data with ListTile from Firestore Database. And while pulling the data from the database, I got the exception below. The names of all the attributes in the database and code are all same. I have no idea why it throws it.

The following assertion was thrown:
An exception was throw by _MapStream<QuerySnapshot<Map<String, dynamic>>, List<Stuff>> listened by

StreamProvider<List<Stuff>?>, but no `catchError` was provided.

Exception:
type 'int' is not a subtype of type 'String'

Here is my stuff.dart:

class Stuff {
  final String title;
  final String details;
  final String price;

  Stuff({
    required this.title,
    required this.details,
    required this.price,
  });
}

Here is my database.dart:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:unistuff_main/models/stuff.dart';

class DatabaseService {
  final String? uid;
  DatabaseService({this.uid});

  //collection reference
  final CollectionReference stuffCollection =
      FirebaseFirestore.instance.collection('stuffs');

//stufflist from snapshot
  List<Stuff> _stuffListFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map((doc) {
      return Stuff(
        title: doc.get('title') ?? '0',
        price: doc.get('price') ?? '0',
        details: doc.get('details') ?? '0',
      );
    }).toList();
  }

//get the stuffs
  Stream<List<Stuff>> get stuffs {
    return stuffCollection.snapshots().map(_stuffListFromSnapshot);
  }
}

Here is my stuff_list.dart:

import 'package:flutter/material.dart';
import 'package:unistuff_main/models/stuff.dart';
import 'package:provider/provider.dart';
import 'package:unistuff_main/screens/home/stuff_tile.dart';

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

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

class _StuffListState extends State<StuffList> {
  @override
  Widget build(BuildContext context) {
    final stuffs = Provider.of<List<Stuff>?>(context);
    //print(stuffs?.docs);
    if (stuffs != null) {
      stuffs.forEach((stuff) {
        print(stuff.title);
        print(stuff.details);
        print(stuff.price);
      });
    }
    return ListView.builder(
      //number of the items in list
      itemCount: stuffs?.length ?? 0,
      //return a function for every item in the list
      itemBuilder: (context, index) {
        return StuffTile(stuff: stuffs![index]);
      },
    );
  }
}

and stuff_tile.dart:

import 'package:flutter/material.dart';
import 'package:unistuff_main/models/stuff.dart';

class StuffTile extends StatelessWidget {
  //const StuffGrid({ Key? key }) : super(key: key);

  //sending the data to stuff
  final Stuff? stuff;
  StuffTile({this.stuff});

  @override
  Widget build(BuildContext context) {
    //creating the list view
    return Padding(
        padding: EdgeInsets.only(top: 8.0),
        child: Card(
          margin: EdgeInsets.fromLTRB(20.0, 6.0, 20.0, 0.0),
          child: ListTile(
              leading: CircleAvatar(
                radius: 25.0,
                backgroundColor: Colors.brown,
              ),
              title: Text(stuff!.title),
              subtitle: Text(stuff!.details)
              ),
        ));
  }
}

Anything would help!


Solution

  • I searched a lot and seen different methods but i couldn't see how to implement those into my own code. So, I go with a different and more basic method, which you can read it from here.

    So, I deleted almost all the files above. Instead of i just use the stuff_list.dart file as my main listing file. Then, I called it from my home.dart file. So, everything works clean at the moment.

    import 'package:cloud_firestore/cloud_firestore.dart';
    import "package:flutter/material.dart";
    
    class StuffList extends StatelessWidget {
      const StuffList({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: _stuffList(),
        );
      }
    }
    
    class _stuffList extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final Stream<QuerySnapshot> _usersStream =
            FirebaseFirestore.instance.collection('Stuffs').snapshots();
    
        return StreamBuilder<QuerySnapshot>(
            stream: _usersStream,
            builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
              if (snapshot.hasError) {
                return Text('Something went wrong');
              }
    
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Text("Loading");
              }
    
              return ListView(
                children: snapshot.data!.docs.map((DocumentSnapshot document) {
                  Map<String, dynamic> data =
                      document.data()! as Map<String, dynamic>;
                  return ListTile(
                    title: Text(data['title']),
                    subtitle: Text(data['details']),
                  );
                }).toList(),
              );
            });
      }
    }
    

    But I won't accept my answer as an answer because this is kind of unrelated to my question. Because it doesnt fix the problem i had above. It just bypass it.