Firebase Firestore – Real-Time, Scalable NoSQL Database in Android - Textnotes

Firebase Firestore – Real-Time, Scalable NoSQL Database in Android


Learn how to integrate Firebase Firestore into your Android app to perform CRUD operations for storing and syncing data in real-time. Firebase Firestore offers a NoSQL cloud database with powerful features like real-time data syncing, offline support, and easy scalability.

Firebase Firestore is a cloud-based NoSQL database that allows you to store, sync, and retrieve data in real-time. It is designed for scalability and supports seamless syncing across devices and platforms. Firestore offers a more powerful, flexible alternative to the Firebase Realtime Database and is ideal for applications that need to manage complex, structured data with real-time synchronization.

i) Setting Up Firebase Firestore in Your Android App

Before we dive into CRUD operations, let’s first set up Firebase Firestore in your Android project.

Step 1: Add Firebase to Your Android Project

  1. Go to the Firebase Console: Firebase Console.
  2. Create a new project or select an existing project.
  3. Add your Android app to the project and download the google-services.json file.
  4. Place the google-services.json file into the app/ directory of your Android project.
  5. In your app-level build.gradle file, add the following dependencies:

dependencies {
implementation 'com.google.firebase:firebase-firestore:24.0.0' // Firestore
}

Then sync the project with Gradle.

Step 2: Initialize Firestore

Initialize Firestore in your Android app:


val db = FirebaseFirestore.getInstance()

Now you are ready to interact with Firestore.

ii) Firestore Data Model

In Firestore, data is stored in collections, and collections contain documents. Documents are essentially key-value pairs, and each document can contain subcollections.

  1. Collection: A group of documents.
  2. Document: A record in a collection.
  3. Field: A key-value pair within a document.

Example: Firestore Data Structure


users (Collection)
-> userId (Document)
-> name: "John Doe"
-> age: 30
-> email: "john.doe@example.com"

iii) Firestore CRUD Operations

Here’s how you can perform CRUD operations (Create, Read, Update, and Delete) using Firebase Firestore in Android.

1. Create (Add) Data

To add a document to a Firestore collection, you can use add() or set().

  1. add(): Automatically generates a unique ID for the document.
  2. set(): Allows you to specify the document ID.
Example: Using add() to create a new document:

val user = hashMapOf(
"name" to "John Doe",
"age" to 30,
"email" to "john.doe@example.com"
)

db.collection("users")
.add(user)
.addOnSuccessListener { documentReference ->
Log.d("Firestore", "DocumentSnapshot added with ID: ${documentReference.id}")
}
.addOnFailureListener { e ->
Log.w("Firestore", "Error adding document", e)
}
Example: Using set() to create a document with a specific ID:

val userId = "user123"
val user = hashMapOf(
"name" to "John Doe",
"age" to 30,
"email" to "john.doe@example.com"
)

db.collection("users").document(userId)
.set(user)
.addOnSuccessListener {
Log.d("Firestore", "DocumentSnapshot successfully written!")
}
.addOnFailureListener { e ->
Log.w("Firestore", "Error writing document", e)
}

2. Read Data

You can retrieve data from Firestore using get() or real-time updates using addSnapshotListener().

Example: Using get() to read a document:

db.collection("users").document("user123")
.get()
.addOnSuccessListener { document ->
if (document != null) {
val name = document.getString("name")
val age = document.getLong("age")
Log.d("Firestore", "Name: $name, Age: $age")
} else {
Log.d("Firestore", "No such document")
}
}
.addOnFailureListener { exception ->
Log.w("Firestore", "Error getting document", exception)
}
Example: Real-time data with addSnapshotListener:

db.collection("users").document("user123")
.addSnapshotListener { documentSnapshot, e ->
if (e != null) {
Log.w("Firestore", "Listen failed.", e)
return@addSnapshotListener
}

if (documentSnapshot != null && documentSnapshot.exists()) {
val name = documentSnapshot.getString("name")
val age = documentSnapshot.getLong("age")
Log.d("Firestore", "Name: $name, Age: $age")
} else {
Log.d("Firestore", "Current data: null")
}
}

3. Update Data

To update a document, use the update() method. You can update specific fields in a document.

Example: Updating a specific field:

db.collection("users").document("user123")
.update("age", 31)
.addOnSuccessListener {
Log.d("Firestore", "DocumentSnapshot successfully updated!")
}
.addOnFailureListener { e ->
Log.w("Firestore", "Error updating document", e)
}

4. Delete Data

You can delete a document using the delete() method.

Example: Deleting a document:

db.collection("users").document("user123")
.delete()
.addOnSuccessListener {
Log.d("Firestore", "DocumentSnapshot successfully deleted!")
}
.addOnFailureListener { e ->
Log.w("Firestore", "Error deleting document", e)
}

iv) Firestore Querying

You can query Firestore collections based on specific fields.

Example: Querying users older than 25:

db.collection("users")
.whereGreaterThan("age", 25)
.get()
.addOnSuccessListener { result ->
for (document in result) {
Log.d("Firestore", "${document.id} => ${document.data}")
}
}
.addOnFailureListener { exception ->
Log.w("Firestore", "Error getting documents: ", exception)
}

You can also combine multiple conditions using whereEqualTo(), orderBy(), and limit().

v) Firestore Offline Support

Firestore provides built-in support for offline data persistence. Once enabled, Firestore will cache the data locally, so your app can continue to read and write data even when the device is offline.

To enable offline persistence:


FirebaseFirestore.getInstance().firestoreSettings = FirebaseFirestoreSettings.Builder()
.setPersistenceEnabled(true) // Enable offline data persistence
.build()

vi) Benefits of Firestore

  1. Real-time Synchronization: Firestore automatically syncs data across all devices, allowing users to see real-time updates.
  2. Scalability: Firestore is designed to scale automatically, handling large amounts of data and high traffic.
  3. Offline Support: With offline persistence, your app can work even when the network is unavailable.
  4. Security: Firestore integrates with Firebase Authentication for fine-grained security control and data access rules.
  5. Flexible Data Model: Firestore supports nested data structures with documents and collections, making it flexible for complex data models.

vii) Conclusion

In this tutorial, we’ve learned how to integrate Firebase Firestore into your Android app and perform CRUD operations to manage your app data. Firestore allows you to easily store and sync data across devices, making it perfect for applications requiring real-time data updates and offline support.

By using Firestore, you can quickly scale your app’s database needs without worrying about managing server infrastructure or complex database systems.