Blog · · 3 min read

Firebase Database in Flutter – WeightTracker 3

In this post, I’m going to go through adding Firebase Database to a Flutter application. The presented development is part of my Weight Tracker app (simple app for tracking weight), so the development will be based on that and focused on that purpose.

Let’s get to it!

Setting up Firebase

The first thing we need to do is set up Firebase integration. It is clearly explained in Firebase’s Codelab, so before moving on I would recommend you going through point 5 in order to connect to Firebase.

For this course we are not going to use Authentication, however, the default rules for Firebase Database require users to be authenticated. To change that we will modify database’s rules file to allow anyone to read and write to the database:

firebase_rules
{
"rules": {
".read": true,
".write": true
}
}

After we set everything up, all we need is to add firebase dependency to our flutter project’s pubspec.yaml file

pubspec.yaml
dependencies:
flutter:
sdk: flutter
firebase_database: 0.0.12

and we are ready to go!


Pushing data to database

Firebase database plugin is very simple to use. To get main reference of our application all we need to do is get access to static field in FirebaseDatabase class.

final mainReference = FirebaseDatabase.instance.reference();

If we would like to get into more specific child of our database, we can simply call mainReference.child(“name_of_child”).

To push an object into database we can just call push and set methods on reference object.

mainReference.push().set(...);

However, the set method doesn’t accept just an object. It needs to be a dynamic value already in a json-map format. In order to transform our object to the format we want, I added toJson method:

weight_entry.dart
class WeightEntry {
DateTime dateTime;
double weight;
String note;
WeightEntry(this.dateTime, this.weight, this.note);
toJson() {
return {
"weight": weight,
"date": dateTime.millisecondsSinceEpoch,
"note": note
};
}
}

Now we can call

mainReference.push().set(entry.toJson())

And we end up with an entry stored in our database.

{
"-KsUdXjd1VSn7iB1s9xo" : {
"date" : 1503769535565,
"weight" : 60
}
}

Reading data form database

In order to get data from the database, we add a listener to the reference we are interested in (in that case it will be mainReference). Once we get the value, we will simply add it to the state’s list and call setState method.

Side note: I present only getting value from database and adding it to the local list. If you are interested in how to display it, check out my GitHub repository for full code. The link provided at the end of the post.

home_page.dart
class _HomePageState extends State<HomePage> {
List<WeightEntry> weightSaves = new List();
_HomePageState() {
mainReference.onChildAdded.listen(_onEntryAdded);
}
_onEntryAdded(Event event) {
setState(() {
weightSaves.add(new WeightEntry.fromSnapshot(event.snapshot));
});
}
...
}
weight_entry.dart
import 'package:firebase_database/firebase_database.dart';
class WeightEntry {
String key;
DateTime dateTime;
double weight;
String note;
WeightEntry(this.dateTime, this.weight, this.note);
WeightEntry.fromSnapshot(DataSnapshot snapshot)
: key = snapshot.key,
dateTime =
new DateTime.fromMillisecondsSinceEpoch(snapshot.value["date"]),
weight = snapshot.value["weight"].toDouble(),
note = snapshot.value["note"];
toJson() {
return {
"weight": weight,
"date": dateTime.millisecondsSinceEpoch,
"note": note
};
}
}

As you can see, database listener consumes Event object. The actual object we are interested in is in event.snapshot.value. However, it is the same dynamic format we have pushed. In order to parse it to WeightEntry, I added constructor accepting DataSnapshot and then getting specific fields from value. I also added Key to the class, which is the unique value Firebase is creating on push. It will be needed in editing.


Updating data

Since we added Key to the WeightEntry model, it is very easy to update a value in the database.

Code below shows how to edit value in database once we have the object we want to pass:

_pushEdit(WeightEntry weightEntry) {
mainReference.child(weightEntry.key).set(newEntry.toJson());
}

Calling child*(key)* will return a reference to the object we want to edit, then setting new value will make a deal. This action will result in an updated entry in the database, however, our application won’t notice it. In order to stay updated with data edits, we need to add a change listener.

home_page.dart
class _HomePageState extends State<HomePage> {
List<WeightEntry> weightSaves = new List();
_HomePageState() {
mainReference.onChildAdded.listen(_onEntryAdded);
mainReference.onChildChanged.listen(_onEntryEdited);
}
_onEntryEdited(Event event) {
var oldValue = weightSaves.singleWhere((entry) => entry.key == event.snapshot.key);
setState(() {
weightSaves[weightSaves.indexOf(oldValue)] = new WeightEntry.fromSnapshot(event.snapshot);
});
}
...
}

Now on every child changed in mainReference, we update this child in our local listView and call setState.

BONUS: If you want your application to store data in local memory in case of no network connection, this is the way 🙂

FirebaseDatabase.instance.setPersistenceEnabled(true);

End notes

Wiring up Flutter application with Firebase is very easy and straight forward. I strongly encourage everyone to try it out. In the near future, I will go through Firebase Authentication for more complex usage of Firebase (link will be provided). If you are interested in more Flutter-Firebase content, you can see the Codelab I talked about earlier. You can also check out firebase_database plugin itself.

I hope you liked that post 🙂

That’s it, folks!

You can find the whole project here. (You need to create own google-services.json to connect to Firebase)