How to use Firebase Queries In Flutter

Peter
Firebase Tips & Tricks
6 min readFeb 16, 2020

Note: This post was originally published on February 2020 and has been completely revamped and updated for accuracy and comprehensiveness.

In this article, we will go more in depth in using Firebase realtime database in flutter, and we will also see how easily you can query, retrieve the data, and add it to a listview.

Note: You can find the source code for all the Firebase/Flutter tutorials in the following repository: Firebase-Flutter-tutorials. Support me by starring the repository and following me on Github for more awesome content! You can also subscribe to my newsletter and join me at Discord! Let’s get started 😁

Creating a Form

Since, we need to add a list of data to the Firebase realtime database, then first we will create a form and when clicking submit, we will send the data to the database.

Note: If you did not setup Firebase, please check the previous tutorial.

So, first to create a form you need to use the widget Form(). The reason why we use a Form() is because it contains validation which is different than just using normal TextFields. Let's take this step by step:

We create a StatelessWidget, that will return a MaterialApp widget and inside of it we call the MyHomePage widget.

Then we declare, the MyHomePage class which will extend the StatefulWidget class, which also means that this widget will have mutable state. Then we override the method createState which creates the mutable state for this widget at a given location in the tree.

Inside the _HomePageState, we override the method build, and we wrap the Column widget with the SingleChildScrollView which will enable us to scroll this whole Column (it is the same as using ScrollView in android). Inside the Column widget we add a Text widget with the text Please Register Your Pet, and the RegisterPet() widget.

So of course first we use createState to create a mutable state and here we declare the class _RegisterPetState. Inside of the class, we use a GlobalKey, which uniquely identifies the Form, and allows validation of the form in a later step. We also create a reference to the node pets in the firebase realtime database. Then inside the form widget, we use a TextFormField:

The TextFormField will let us, use the validator property that validates an input. The full code for main.dart:

The result:

Saving the List to Firebase

To save the list to firebase, we first need an random id that can seperate the data. Fortunately, firebase provides the method push() which will do just that:

So here dbRef refers to the node pets, the push() method will create a random id, and the set method will contain the data from the form. The then() callback will execute after the data is added in the Firebase database, and you can use the catchError which will handle errors emitted by this Future. (This is the asynchronous equivalent of a "catch" block). The Firebase realtime database:

Retrieving The Firebase Data in a ListView

To retrieve the list, first we need to get a reference to the node. We do that by using the method child():

final dbRef = FirebaseDatabase.instance.reference().child("pets");

Then we use the FutureBuilder widget. You can learn more about it here, basically the FutureBuilder will make it easily to use the result of an asynchronous call with a flutter widget.

We assign dbRef.once() which returns a Future<DataSnapshot> to the future property, this will retrieve the data only once. Since this is asychronous, then first the widget CirculareProgressIndicator will be executed, then if the snapshot has data, the code inside the if block will get executed. Inside the if block, we use the property value of type DataSnapshot that will retrieve the whole returned data. Then using forEach, we can iterate and add the property values to the list. After that, we declare a listview using ListView.builder constructor, we also use the card widget to be used on the list.

Another way to retrieve data, is to use the StreamBuilder widget:

In this case, you need to use the event onValue, which fires when the data at this location is updated. So, if you update the database, then automatically the listview will get updated.

Executing Different Firebase Queries

So first you need to order the data by something specific, in the firebase_database we have the following methods:

orderByValue: Generate a view of the data sorted by value, intended to be used in combination with startAt, endAt, or equalTo.

orderByPriority: Generate a view of the data sorted by priority, intended to be used in combination with startAt, endAt, or equalTo.

orderByChild: Generate a view of the data sorted by values of a particular child key, intended to be used in combination with startAt, endAt, or equalTo.

orderByKey: Generate a view of the data sorted by key, intended to be used in combination with startAt, endAt, or equalTo.

Note: You cannot use two orderBy.. methods in the same query.

The method orderBy.., can be used with the following methods:

startAt: Create a query constrained to only return child nodes with a value greater than or equal to the given value.

endAt: Create a query constrained to only return child nodes with a value less than or equal to the given value.

limitToFirst: Create a query with limit and anchor it to the start of the window.

limitToLast : Create a query with limit and anchor it to the end of the window.

Now, if you use the following query:

dbRef.orderByChild("age").equalTo("4").once(),

Then you will get only the nodes that have age equal to 4:

dbRef.orderByKey().equalTo("-M0FIuRBi5NT1VKsTbQt").once(),

If you use the above query, then you will retrieve the node that contains the key -M0FIuRBi5NT1VKsTbQt

dbRef.orderByChild("name").startAt("s").once()

If you use the above query, then you will retrieve all the data that has a node name with first letter equal to sor greater than s :

ref.orderByChild("name").startAt("bun").endAt("bun" + "\uf8ff").once()

or

ref.orderByChild("name").startAt("bun").endAt("bun" + "\uf8ff").limitToFirst(1).once()

limitToFirst will only return the first element that satisfies the condition above.

Here its like you are using SQL like. The character \uf8ff used in the query is a very high code point in the Unicode range. Because it is after most regular characters in Unicode, the query matches all values that start with "bun".

In this case, it will return the following:

ref.orderByChild("name").endAt("n").once()

So here, it is like you are saying find all pets whose names come before n lexicographically. In this case, it will return the following:

ref.orderByChild("name").startAt("la").once()

So, here we use startAt("la"), remember startAt returns child nodes with a value greater than or equal to the given value. So in this case, it will return the following:

Since both s and m are alphabetically higher than l.

You can find the source code here: Firebase Database Tutorial

I hope you enjoyed this Flutter/Firebase article, in the next article I will use firebase authentication with realtime database

Originally published at https://petercoding.com on February 16, 2020.

--

--

Peter
Firebase Tips & Tricks

Software Developer. Actively helping users with their Firebase questions on Stack Overflow. Occasionally I post on medium and other platforms.