Firebase RealTime database Flutter stream never returns problem

292

Solution 1

Try the following

!snapshot.hasData || snapshot.data.documents.isEmpty

The problem here is that snapshots() will also return a QuerySnapshot when the query returns no documents. Thus, you could expand your condition like this:

Here is what I have should help you

if (snapshot.hasError) {
            //TODO: we need to make sure we caputer this error message snapshot.error
            return const PlaceHolder(
              url: 'assets/animations/404-error.json',
              message: ErrorMessages.getDogsError,
            );
          } else if (snapshot.data == null || snapshot.data!.isEmpty) {
            return const PlaceHolder(
              url: 'assets/animations/no-dog-animation.json',
              message: AppMessages.noDogMessage,
            );
          } else if (!snapshot.hasData) {
}

Solution 2

Your problem is that you most likely have an error.
The issue is, your error handling is actually never reached, because in case of an error, !hasData will still be true

You may want to execute the hasError condition before !hasData:

if (snapshot.hasError) {
  return Text('error');
} else if (!snapshot.hasData) {
  return Text('loading');
} else {
  return Text('data');
}
Share:
292
edn
Author by

edn

And I am a big Machine Learning enthusiast. I am particularly focusing on Deep Neural Networks, Tensorflow and Python. You are welcome to get in touch for any discussion for closer cooperation.

Updated on January 03, 2023

Comments

  • edn
    edn over 1 year

    I am trying to read a list of objects from Realtime database in Firebase with no success so far.

    I am following the official tutorial from Firecasts on the following link: https://www.youtube.com/watch?v=sXBJZD0fBa4

    Here is how the database looks like: enter image description here

    Here is the code I have written:

    The following is the class I have created for the objects I will be reading from database:

    class TestData {
      final String name;
      final String surname;
      final String age;
    
      TestData({
        required this.name,
        required this.surname,
        required this.age,
      });
    
      factory TestData.fromRTDB(Map<dynamic, dynamic> data) {
        return TestData(
          name: data["Name"],
          surname: data["Surname"],
          age: data["Age"],
        );
      }
    }
    

    Here is how I try to read it from the database:

    class TestDataGetter {
      final _db = FirebaseDatabase.instance.ref();
    
      Stream<List<TestData>> getTestDataStream() {
        final csPostprocessedStream = _db.child("test_data/").onValue;
        var streamToPublish = csPostprocessedStream.map((event) {
          final testDataMap = Map<dynamic, dynamic>.from(
              event.snapshot.value as Map<dynamic, dynamic>);
    
          final testDataList = testDataMap.entries.map((element) {
            return TestData.fromRTDB(Map<dynamic, dynamic>.from(element.value));
          }).toList();
          return testDataList;
        });
        return streamToPublish;
      }
    }
    

    And here is the screen where I would like to show the data:

    class TestDataScreen extends StatelessWidget {
      const TestDataScreen({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            children: [
              StreamBuilder(
                  stream: TestDataGetter().getTestDataStream(),
                  builder: (context, snapshot) {
                    if (!snapshot.hasData) {
                      print("Waiting");
                      return const CircularProgressIndicator(color: Colors.white);
                    } else if (snapshot.hasError) {
                      print("Error occured...");
                      return const CircularProgressIndicator(color: Colors.white);
                    } else {
                      final testDataList = snapshot.data as List<TestData>;
                      return Text(
                          testDataList[0].name + " / " + testDataList[1].name,
                          style: Theme.of(context).textTheme.headline3,
                          textAlign: TextAlign.center);
                    }
                  }),
            ],
          ),
        );
      }
    }
    

    But I can never see the data on the screen. The spinning wheel is the only thing I see and on the console I see the print out as "Waiting" (as I print out this text in the code above).

    It gets stuck in if (!snapshot.hasData).

    I am clueless after spending hours on this.

  • edn
    edn over 2 years
    There is do "documents" in Realtime databaase. Documents belongs to the world of Firestore. Or, am I interpreting your answer wrong?
  • Almog
    Almog over 2 years
    Check the docs its might be data, I stopped using the real-time DB as it's not really not getting worked on. But I think you just need to check if the returned snapshot is being return but is empty
  • Almog
    Almog over 2 years
    Check now I add my code as an example might help you
  • edn
    edn over 2 years
    Thank you. It is really the case that you need to check if there are any errors before checking if there is any data. I just left it some days, and now went back and run it again by checking the error message first and it worked. I have no clue what made it work this time bcz just checking the error message first should not make it work but it happened to be the case.
  • edn
    edn over 2 years
    Thank you. It is really the case that you need to check if there are any errors before checking if there is any data. I just left it some days, and now went back and run it again by checking the error message first and it worked. I have no clue what made it work this time bcz just checking the error message first should not make it work but it happened to be the case.