Flutter — Server-less CRUD operations with Firebase

Rawaha Muhammad
7 min readOct 9, 2023

In this short tutorial, we are going to learn how to perform simple CRUD operations using Firebase Cloud Firestore.

So what is CRUD?

CRUD stands for Create, Read, Update, and Delete.

A software program should be able to perform actions on the data that it holds. In our case, our Flutter mobile application should be able to create, read, update, and delete the data that it holds.

For holding this data, we will be using Firebase Cloud Firestore.

More information about Cloud Firestore can be found on the Firebase official documentation website.

Since Firebase Cloud Firestore is serverless, it cannot manipulate data on its own, and we need to call methods from the mobile side in order to perform CRUD operations on our data that is stored in the Firebase Cloud Firestore. This tutorial will cover exactly that.

First, integrate Firebase with your Flutter project

Create a new Flutter project and integrate Firebase with it.

Don’t worry if you don’t know how to integrate Firebase with Flutter. I have written an article just for that purpose.

Now we need to set up Cloud Firestore

Once Firebase is integrated with your Flutter project, we now need to add Cloud Firestore to our Firebase project through the Firebase Console.

Go to the Firebase Console and click on your project, in our case, this will be runtimesnippets-firebase-test

Project screen in Firebase console

Now in the left menu, expand the Build menu, and click on Firestore Database

Build menu in Firebase Console Project Overview page

Then, click on the Create Database button

Cloud Firestore option to Create database

Once you do this, you will be prompted with a Dialog with two steps.

Dialog for database rules and location with production mode selected

The first step is to select your security rules. Here, the production mode is for production apps, and the test mode is for testing our apps.

By default, the production mode offers security rules that do not allow for any reads or writes. Similarly, the test mode offers security rules that allow for reads or writes for a month.

Dialog for database rules and location with test mode selected

An important thing to note here is that test mode allows anyone with your database reference to view, edit, and delete all data in your database.

Now, click Next, and then select your database location. This will be the location where your Cloud Firestore data will be stored. Depending on which region you choose, the response time for reads and writes may differ but do not worry, it does not make a huge impact.

For this tutorial, we will use Multi-region eur3 (Europe).

Location selection for database

Click Enable and your database is now ready to go.

Cloud Firestore database enabled

Go ahead and experiment with the data, try to create a collection, then assign it a document ID, and then add fields and their values. The documents are always key-value pairs and can store multiple fields, just like a HashMap in programming.

Cloud Firestore with data

Here, we have created a collection called “users” and then a document called “runtime”, which is a user's username. Inside this document, we have added a key “email” and its value “email@email.com”.

If we want to add more users, we can append them to the list of documents by adding another document ID according to the username.

We can now move on to the coding part

Add Cloud Firestore as a dependency in your Flutter project

cloud_firestore: ^4.9.3

Then try to run the app.

If you are running the app on iOS, an error like this should come up.

error after importing the cloud_firestore package

Do not worry, go to your IDE terminal, and at the root of the Flutter project, run cd ios and then after that, run pod update
This will download the required pods needed to run the app.

terminal after running “pod update”

Now run the app again, and we should be able to see the signature Flutter counter app UI.

Since we are focusing on performing operations on Firebase Cloud Firestore, we will try to keep our interaction with the app UI to a minimum. We will use log methods to verify our CRUD data.

Our app is ready, and integrated with Firebase at this point, all we need to do now is focus on performing the CRUD operations!

Let’s perform a Read operation…

Now go to main.dart and just after we have initialized our Firebase app, get a reference to our Cloud Firestore database.

final FirebaseFirestore db = FirebaseFirestore.instance;

Once we have the database reference, we can then get the “users” collection we created in the Firebase console, by calling the collections method of the Firestore database reference and passing it the path to our collection, which was users

final CollectionReference users = db.collection('users');

Once we have the collection reference, we can get the document by the document ID we created, which was “runtime” to access the Map for the document fields.

final DocumentSnapshot snapshot = await users.doc('runtime').get();

To access the fields, we need to call the data method of the DocumentSnapshot class.

final userFields = snapshot.data();

Finally, we can use the log method to log this information to our debug console and view the fields.

the main method after we have written our read operation code
the logged information on the debug console after we have written our read operation code

In order to access this object, we need to cast the userFields Object type to a Map type and then log it

final userFields = snapshot.data() as Map<String, dynamic>;
log(userFields['email']);

And then we should be able to see the email field.

the logged information on the debug console after we have written our read operation code

We just performed our Read operation.

Let’s move to the Create operation

We will create a new document in the “users collection. And doing this is very simple.

We need the collection reference for the “users” collection, after which we can use the doc method to get the document reference and pass it the name of our new document, which is a new user called “newUser”, so that we can use the set method to pass a Map that will set the fields for the new document.

It does not matter which structure you used to create the old document, the new document can be of any structure! But be wary, this flexibility can break our app if we hard code our read operation logic.

The main method after we have written our create operation code

Once this code is run through Flutter’s hot reload, we should be able to see the change in the Firebase Console.

New document created in Firebase Console with our fields

Let’s try to update the email field

All we need to do in order to update the email field is to use the update method instead of theset method of the DocumentReference class.

The main method after we have written our update operation code

Once this code is run, hot reload the app and check the Firebase Console fields, the email should now be updated.

Field updated in Firebase Console

Delete a document

Deleting is extremely simple! Just replace the update method with the delete method and hot reload

The main method after we have written our delete operation code

You should be able to see that the “newUser” document has now been deleted from the Firebase Console

Document deleted in Firebase Console

And that’s a wrap!

We have successfully mastered how to write CRUD operations in our Flutter app using the Firestore database.

If you liked the tutorial…

Please follow me here and on my socials!

Follow me:

LinkedIn: https://www.linkedin.com/in/rawahamuhammad/
Github: https://github.com/coffiie
Medium:

Follow Runtime Snippets (bite-sized Flutter/Dart tutorials)

Youtube: https://www.youtube.com/channel/UCD2BEqL0wC7leFKm4i9_aRg
LinkedIn: https://www.linkedin.com/company/100042850
Twitter: https://twitter.com/runtimesnippets

--

--