skip to Main Content

I’m trying to retrieve data from Firebase. Here’s my code snippet

Future main() async {

  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  // DatabaseReference ref = FirebaseDatabase.instance.ref();
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    final docRef = FirebaseFirestore.instance.collection('data').doc("rules");
    docRef.get().then(
          (DocumentSnapshot doc) {
        final data = doc.data() as Map<String, dynamic>;
        return MyHomePage(title: 'ARNET Helper',
            rules: data['ruleslist']);
      },
      onError: (e) => print("Error getting document: $e"),
    );
    return Spinner(text: "Unable to retrieve data");
  }

}  

Here’s the corresponding Firebase database screenshot
enter image description here

I do have the google-services.json added to the android/app folder. But with the above snippet, lines from the "then" block don’t seem to get hit and the spinner (i.e return Spinner(text: "Unable to retrieve data");) is always returned.

I do have these lines added to AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>

I tried to debug it. But the breakpoint at line 46 is never hit. Instead the execution goes straight to line 52. What am I missing?
enter image description here

I’ve even tried using FutureBuilder as suggested by one of the commenters. I always get "Something went wrong.." spinner

  @override
  Widget build(BuildContext context) {
    CollectionReference data = FirebaseFirestore.instance.collection('data');
    return FutureBuilder<DocumentSnapshot>(
      future:  data.doc('rules').get(),
      builder:
          (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {

        if (snapshot.hasError) {
          return Spinner(text: 'Something went wrong...');
        }

        if (snapshot.hasData && !snapshot.data!.exists) {
          return Spinner(text: 'Document does not exist...');
        }


        if (snapshot.connectionState == ConnectionState.done) {
          Map<String, dynamic> data = snapshot.data! as Map<String, dynamic>;

          return MyHomePage(title: 'ARNET Helper', rules: data['ruleslist'].entries.toList() as List<dynamic>);
        }

        return Spinner(text: 'Loading...');
      },
    );
  }
}

3

Answers


  1. Chosen as BEST ANSWER

    Not sure what the issue was but the config below worked.

    pubspec.yaml

      firebase_core: ^1.24.0
      cloud_firestore: ^3.5.0
    

    FutureBuilder query

    @override
      Widget build(BuildContext context) {
        CollectionReference data = FirebaseFirestore.instance.collection('data');
        return FutureBuilder<DocumentSnapshot>(
          future:  data.doc("rules").get(),
          builder:
              (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
    
            if (snapshot.hasError) {
              return Spinner(text: 'Something went wrong...');
            }
    
            if (snapshot.hasData && !snapshot.data!.exists) {
              return Spinner(text: 'Document does not exist...');
            }
    
    
            if (snapshot.connectionState == ConnectionState.done) {
              final data = snapshot.data!.get('ruleslist') ;
    
              return MyHomePage(title: 'ARNET Helper', rules: data);
            }
    
            return Spinner(text: 'Loading...');
          },
        );
      }
    }
    

  2. Did you initialize the Firebase Instance?

    await Firebase.initializeApp()
    
    Login or Signup to reply.
  3. The problem is that get() is an asynchronous operation, and you can’t return widgets asynchronously in build.

    The simplest way to fix this is to use a FutureBuilder:

    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      return FutureBuilder<String>(
        future: FirebaseFirestore.instance.collection('data').doc("rules").get(),
        builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> asyncSnapshot) {
          if (snapshot.hasData) {
            final data = asyncSnapshot.data!.data() as Map<String, dynamic>;
            return MyHomePage(title: 'ARNET Helper', rules: data['ruleslist']);
          }
          else if (snapshot.hasError) {
            return Text("Error: ${snapshot.error}")
          } 
          else {
            return Text("Loading user data...")
          }    
        }    
      )
    }  
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search