Flutter Firestore getRecord by Value and Output

Advertisements

First, apologies I am a total newb to Flutter, Dart & Firestore and despite trying to follow many tutorials I am stuck.

I am trying to retrieve a Firestore collection record by a specific value.

I have a service dart class which runs the query.

import 'package:cloud_firestore/cloud_firestore.dart';

class WaypointService {

  getWaypointById(int wpCheckPointId) {
    return FirebaseFirestore.instance
        .collection("waypoints")
        .where("CheckPoint", isEqualTo: wpCheckPointId)
        .get();
  }

}

This service is passed an integer from a constant in a constants file. The screen that calls the service is:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:lhgth/services/waypoint_service.dart';

class WaypointScreen extends StatelessWidget {
  const WaypointScreen({ super.key, required this.wpFirebaseID });

  final int wpFirebaseID;

  @override
  Widget build(BuildContext context) {
    var waypoint;
    WaypointService().getWaypointById(wpFirebaseID).then((QuerySnapshot wayPoint) {
      if (wayPoint.docs.isNotEmpty) {
        waypoint = wayPoint.docs.first.data();
        print(waypoint); //##1
      }
    });

    print(waypoint); //##2

    return Container(
      padding: EdgeInsets.all(8),
      child: Scaffold(
        backgroundColor: Colors.white,
        body: Container(

        ),
      )
    );
  }
}

The issue I have is that the print statement ##1 is outputting what looks to be a JSON value:

{
  Radius: 25,
  Long: 50.9491835, 
  Info: Text,
  Lat: 0.7317906,
  CheckPoint: 1,
  Name: Waypoint Name
}

However, the second print ##2 returns a NULL and so I am not sure how I would work with the data returned from the query in the view itself.

Any guidance would be helpful.

>Solution :

That’s totally normal, the get() method is an async method you have to wait before it returns the value.

The second print ##2 returns null because it called before the getWaypointById method finishes.

First: make your getWaypointById method as Future like this:

Future<QuerySnapshot> getWaypointById(int wpCheckPointId) {
    return FirebaseFirestore.instance
        .collection("waypoints")
        .where("CheckPoint", isEqualTo: wpCheckPointId)
        .get();
}

Then: instead of doing tests in the build method, you can test in an external method like this:

test() async {
    var waypoint;
    var results = await getWaypointById(wpFirebaseID);
    if (results.docs.isNotEmpty) {
      waypoint = results.docs.first.data();
    }
    print(waypoint);
  }

Then you can call the test method in the build.

To show the value on the screen you can use FutureBuilder:

class WaypointScreen extends StatelessWidget {
  const WaypointScreen({ super.key, required this.wpFirebaseID });

  final int wpFirebaseID;

  @override
  Widget build(BuildContext context) {

    return Container(
        padding: EdgeInsets.all(8),
        child: Scaffold(
          backgroundColor: Colors.white,
          body: Container(
            child: FutureBuilder<QuerySnapshot>(
              future: WaypointService().getWaypointById(wpFirebaseID),
              builder: (context, snapshot) {
                if (snapshot.hasData && (snapshot.data?.docs.isNotEmpty?? false)) {
                  var waypoint = snapshot.data!.docs.first.data();
                  return Text(waypoint['Name']);
                } else {
                  return Text('Loading...');
                }
              },
            ),
          ),
        )
    );
  }
}

Leave a ReplyCancel reply