Beginning FlutterFire

Aug 30 2022 · Dart 2.16, Flutter 3.0, Visual Studio Code 1.69

Part 3: Read & Write Data with the Cloud Firestore

11. Insert & Retrieve Data from Firestore

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 10. Create the Model Class Next episode: 12. Create the Activities Screen

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 11. Insert & Retrieve Data from Firestore

Now that you’ve created the Activity model class, the Firestore database and added all the dependencies in your project, you can finally write the methods that allow retrieving and writing data to the database.

Open the firebase_helper.dart file. Let’s begin with the method that adds a new activity into the database.

In the FirebaseHelper class, add a new method. As usual when dealing with Firebase, this is asynchronous, and it returns a Future of “DocumentReference”: we can call this insertActivity.

A DocumentReference is as you can expect, a reference to a Firestore document: you can use it to read or write a document in a collection. It’s important to note that you can get a reference even if the document does not exist.

The insertActivity method takes an Activity as its only parameter, that you can call activity. We’ll mark this async. Inside the method, declare a final newActivity that awaits the activities.add method, passing activity.toMap.

The add method of a Firestore collection, adds a document into the collection itself. Put your mouse pointer over the add method: as you can see, this method returns a Future of DocumentReference, and takes an optional object as its only parameter. Here you just pass the toMap method over the activity you want to insert into the Collection. As you might remember, this transforms an Activity object into a Map, so that each key of the map will become a Key into the Firestore document, and likewise each value will set the value at its key in the Firestore document.

Finally return newActivity to the caller.

Future<DocumentReference> insertActivity(Activity activity) async { 
    final newActivity = await activities.add(activity.toMap()); 
    return newActivity; 
  } 

As you can see adding a document into a Firestore database is easy. Now it would probably be a good idea to insert this code into a try catch block. So, select our code, and press the bulb to show the code actions you can perform here. Next select the “surround with try catch” action.

In the catch section, during debug you we want to print the error: so, let’s print e.toString. Then just return null. This requires a small change in our code, as the documentReference we return may be null: just add a question mark near DocumentReference to solve this issue.

  Future<DocumentReference?> insertActivity(Activity activity) async { 
    try { 
      final newActivity = await activities.add(activity.toMap()); 
      return newActivity; 
    } on Exception catch (e) { 
      print(e.toString()); 
      return null; 
    } 
  } 

OK, now that we can write data to the database, let’s also create a method to retrieve the data you have added. This will return a future of a list of activity objects. Call it readActivities, and mark it as async. Now, declare a QuerySnapshot of dynamic, called snapshot, that awaits activities.get.

The get method, called over a collection, returns a Querysnapshot containing all the documents in the collection itself. A Querysnapshot contains zero or more DocumentSnapshot objects.

So, let’s create another final variable, that will be a List of Activty, that will be empty. Now let’s cycle through the Querysnaption with a for loop:

For i that starts at 0, until i is less than the length of snapshot.docs, I++ .

Declare a final activity, that calls the Activity fromMap method, passing snapshot.docs[i].data() as Map<String, dynamic>, and the id of the document at snapshot.docs[i].id. Next, add the activity to the list. When the for loop is over, return the list itself.

  Future<List<Activity>> readActivities() async { 
    final QuerySnapshot<dynamic> snapshot = await activities.get(); 
    final List<Activity> list = []; 
    for (var i = 0; i < snapshot.docs.length; i++) { 
      final activity = Activity.fromMap( 
          snapshot.docs[i].data() as Map<String, dynamic>, snapshot.docs[i].id); 
      activity.id = snapshot.docs[i].id; 
      list.add(activity); 
    } 
    return list; 
  } 

Let’s put all this code into a try catch block. In case an exception is raised, let’s print the message of the exception and just return an empty list with no data.

OK, let’s quickly write a method to test our methods before moving on to the UI. So, create a new method, that returns a Future, called testData, async.

Inside the method await for the result of the call to insertActivity. Here we’ll pass a new activity, that will have null as its ID, running for the description, 12/12/2022 for the date, 8.30 startTime, 9.30 endtime, and null for the image. Next, let’s create a final called activities, that will await the result of our readActivities method.

Finally let’s print the first activity description. Of course, we expect it to be “running”, but let’s make sure it works as expected.

Future testData() async { 

    await insertActivity( 
        Activity(null, 'Running', '12/12/2022', '8.30', '9.30', null)); 
    final activities = await readActivities(); 
    print(activities[0].description); 
  } 

So, in the main.dart file, in the build method of myApp, let0s create an instance of FirebaseHelper, called helper. This will import our firebase_helper.dart at the top of the file. Here call the test method over the helper.

    final helper = FirebaseHelper(); 
    helper.testData(); 

Run the app. If everything’s working as expected, after a few seconds you should see “running” in the debug console.

This means that the reading and writing actions to the database are working! Now delete this code, as we don’t need it anymore. Let’s create some User Interface for our users next!