Real-time shared expense tracker app using Flutter and Firebase: Part 5— Using Firebase Realtime Database for storing expense and user data.
Firebase Realtime database is a path based database provided by Google Fiebase for fast CRUD applications, unlike Firestore database where information is stored as documents, here information is stored as nested Maps. So we need pass the data as a json object.
In the last section, we created a Chat UI for viewing past expenses and adding new ones via Firebase Realtime database and FirebaseAnimatedLists package. As mentioned in last section, once Submit button is pressed, we convert the user inputs into the message class object which then is used to update information on the database in the chats path. Similarly, when passing user data, we can create user data class. Both classes have a toJson method.
class MessageClass {
final String datetime;
final String userId;
final String amount;
final String content;
MessageClass(
{required this.datetime,
required this.userId,
required this.amount,
required this.content});
Map<String, dynamic> toJson() {
return {
"timestamp": datetime,
"userId": userId,
"amount": amount,
"content": content
};
}
}
class UserData {
final String username;
final String uid;
final String devicetoken;
UserData(
{required this.username, required this.uid, required this.devicetoken});
Map<String, String> toJson() {
return {
"uid": uid,
"username": username,
"devicename": devicetoken,
};
}
}
Now we need a method to take this json object and pass it to the database. For that we use the set method, we can also use push method but that will create a random PushID for each new entry. This will create difficulty to then sort data timestamp wise in the chat UI. If there are many users, we should actually use PushID so that many entries at the same instant are entered separately. The timestamp of entry is the new key created while storing the entry.
class FirebaseDatabaseClass {
// for expense entries
static void setValue(MessageClass message) async {
DatabaseReference ref =
FirebaseDatabase.instance.ref("chats/${message.datetime}");
ref.set(message.toJson());
}
// for user information
static void setUserValue(UserData userdata) async {
DatabaseReference ref =
FirebaseDatabase.instance.ref("userdata/${userdata.uid}");
ref.set(userdata.toJson());
}
static Future<Object?> getValues() async {
DatabaseReference ref = FirebaseDatabase.instance.ref('chats');
return ref;
}
}
We also need to setup a few things on the database, which are its rules. On starting the realtime database, it’ll prompt to select a region. After that we need to apply some rules in the rules section to keep the database secure. I have applied some basic read, write rules based on user's authentication id.
{
"rules": {
".read": "auth != null && auth.uid === 'uid_for_user_1' || auth.uid === 'uid_for_user_2'",
".write": "auth != null && auth.uid === 'uid_for_user_1' || auth.uid === 'uid_for_user_2'"
}
}
In the database, the updated text looks like below
chats
1702286794789
amount:"200"
content:"milk"
timestamp:"1702286794789"
userId:"user_uid"
After each expense a new entry with timestamp will be made in the database which can be delete from the firebase portal itself. In the next section we can have a look at how to send notifications to specific users on the summary of their last day’s expenses using Firebase Cloud messaging.