Share
Explore

Lab Workbook: Data Persistence with Firebase Lab Learning Workbook for Android with Kotlin Development

Introduction: (this lab has some duplication to clean up)
In this lab learning workbook, we'll explore data persistence using Firebase in Android with Kotlin development.
We'll cover Android Jetpack Architecture Components, understanding the Firebase database structure, creating documents & collections with Kotlin code, and CRUD operations using Kotlin.

Section 1: Android Jetpack Architecture Components

Introduction to Android Jetpack Architecture Components
LiveData, ViewModel, and Room
Implementing Architecture Components in an Android project using Kotlin

———————

1.1 Introduction to Android Jetpack Architecture Components

Android Jetpack is a suite of libraries, tools, and guidance for developing robust Android applications[2]. It includes Foundation Components, Architecture Components, Behavior Components, and UI Components. In this section, we'll focus on Architecture Components, which help developers avoid lifecycle-related issues and maintain applications more efficiently[2].

1.2 LiveData, ViewModel, and Room

Three key Architecture Components are LiveData, ViewModel, and Room[1]. LiveData is a lifecycle-aware, observable data holder class that keeps data up-to-date and prevents memory leaks[3]. ViewModel is responsible for managing UI-related data, allowing data to survive configuration changes[1]. Room is an SQLite object-mapping library that overcomes SQLite's drawbacks, such as compile-time query checking and the inability to save POJOs[2].

1.3 Implementing Architecture Components in an Android project using Kotlin

To implement Architecture Components in your Android project using Kotlin, follow these steps:
Add the necessary dependencies to your app's build.gradle file[1].
Create a data class to represent your app's data model and add annotations for Room entities[1].
Define a Data Access Object (DAO) interface to interact with the database[1].
Create a Room database class that extends RoomDatabase[1].
Implement a ViewModel to interact with your data model and expose LiveData objects for the UI components[1].
Update your Activity or Fragment to observe LiveData objects and display the data[3].

References:

———————-


Introduction to Android Jetpack Architecture Components:

Android Jetpack Architecture Components is a set of libraries, tools, and guidance that help developers create robust, testable, and maintainable Android apps. It includes a collection of libraries that are built on top of the Android framework and provides a set of best practices, patterns, and guidelines for Android app development. The Architecture Components offer a way to design and develop Android apps that are modular, scalable, and easy to maintain.
The four main components of the Android Jetpack Architecture Components are:
Foundation Components - These components provide a base layer for Android app development, including Kotlin extensions, app compat, and testing.
Architecture Components - These components provide a set of libraries that help developers to build a robust and scalable architecture for their Android apps. Some of the key components of Architecture Components are LiveData, ViewModel, Room, and Navigation.
Behavior Components - These components help developers to add common Android app features such as notifications, permissions, and sharing to their apps.
UI Components - These components help developers to build user interfaces for their Android apps using pre-built components such as RecyclerView, CardView, and ConstraintLayout.

LiveData, ViewModel, and Room:

LiveData, ViewModel, and Room are some of the key components of the Architecture Components that help developers to build a robust and scalable architecture for their Android apps.
LiveData: LiveData is an observable data holder class that is part of the Architecture Components. It allows you to observe changes to data in real-time and update the UI accordingly. LiveData is lifecycle-aware, which means it automatically manages the lifecycle of the data it holds and ensures that the UI is always up-to-date. LiveData is also thread-safe, which means it can be safely accessed from multiple threads.
ViewModel: ViewModel is a class that is part of the Architecture Components. It is designed to store and manage UI-related data in a lifecycle-aware way. ViewModel is responsible for preparing and managing data for the UI. It survives configuration changes, such as screen rotations, so the data is not lost. ViewModel can also communicate with other components, such as LiveData, to provide data to the UI.
Room: Room is a persistence library that is part of the Architecture Components. It provides an abstraction layer over SQLite to allow you to easily store and access data in your Android app. Room uses annotations to generate SQL code for you, which reduces the amount of boilerplate code you need to write. Room also provides compile-time verification of SQL queries, which can help you catch errors early.

Implementing Architecture Components in an Android project using Kotlin:

To implement the Architecture Components in an Android project using Kotlin, follow these steps:
Add the Architecture Components to your project: To use the Architecture Components in your project, you need to add the following dependencies to your app's build.gradle file:

dependencies { def lifecycle_version = "2.4.0" def room_version = "2.4.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" implementation "androidx.room:room-ktx:$room_version"}
Create a ViewModel: To create a ViewModel, you need to create a new class that extends the ViewModel class.
In the ViewModel class, you can define properties to hold your data and methods to manipulate that data. Here is an example of a ViewModel class that holds a list of users:
class UserViewModel : ViewModel() {
private val userRepository = UserRepository()
fun getUsers(): LiveData<List<User>> { return userRepository.getUsers() }
fun addUser(user: User) { userRepository.addUser(user) }

Section 2: Understanding Firebase Database Structure

=====================

Introduction to Firebase Realtime Database and Firestore:

Firebase is a backend-as-a-service (BaaS) platform that provides a range of services for mobile and web application development.
Firebase Realtime Database and Firestore are two popular database options provided by Firebase.
Firebase Realtime Database is a cloud-hosted NoSQL database that stores data in JSON format.
It allows developers to store and sync data in real-time between clients, making it ideal for applications that require real-time updates such as chat apps or live streaming.
Firestore, on the other hand, is a cloud-hosted NoSQL document database that stores data in collections and documents.
Firestore is designed to scale horizontally and can handle large datasets with complex relationships between data.

Firebase Database Structure: JSON tree (Realtime Database) vs.

Collections and Documents (Firestore)

Firebase Realtime Database uses a JSON tree structure to store and retrieve data.
The data is organized as a hierarchy of nodes, with each node represented as a key-value pair. The nodes can have child nodes, and the data is stored in a nested fashion.
For example, consider a simple Firebase Realtime Database structure:

{ "users": { "user1": { "name": "John", "age": 25 }, "user2": { "name": "Mary", "age": 30 } }}
In this example, the "users" node has two child nodes, "user1" and "user2", each containing data for a user.
Firestore, on the other hand, uses a collections and documents structure to store data.
A collection is a group of documents, and each document is a set of key-value pairs.
The documents in a collection do not have to have the same structure, allowing for more flexibility in data modeling. For example, consider a simple Firestore structure:

users (collection) user1 (document) name: "John" age: 25 user2 (document) name: "Mary" age: 30
In this example, "users" is a collection, and "user1" and "user2" are documents in that collection.

Choosing the right database for your project

The choice between Firebase Realtime Database and
Firestore
depends on the specific requirements of your project. If your application requires real-time updates and a simple data structure, Firebase Realtime Database is a good choice.
On the other hand, if you need more complex queries and a flexible data model, Firestore is a better option.
In addition, Firebase Realtime Database has better support for offline data,
while Firestore offers more advanced security features such as role-based access control.
To use either Firebase Realtime Database or Firestore in your application, you need to integrate the Firebase SDK into your project and initialize the database.
You can then use the Firebase APIs to read and write data to the database.
The Firebase SDK provides a set of libraries for various platforms, including Android, iOS, and web.
========================
Introduction to Firebase Realtime Database and Firestore
Firebase Database Structure: JSON tree (Realtime Database) vs. Collections and Documents (Firestore)
Choosing the right database for your project

2.1 Introduction to Firebase Realtime Database and Firestore

Firebase provides two cloud-hosted databases for your mobile and web applications:
Realtime Database and
Cloud Firestore.
Both databases enable real-time data synchronization, offline support, and scalability.
However, they have different data structures, querying capabilities, and pricing models.

2.2 Firebase Database Structure: JSON tree (Realtime Database) vs. Collections and Documents (Firestore)
Realtime Database stores data as a large JSON tree. Each node in the tree is accessible via a unique URL, and you can store simple data types like strings, numbers, booleans, and objects. There's no support for complex queries in Realtime Database
Firestore, on the other hand, uses a document-oriented model where data is stored in documents organized into collections. Each document is a set of key-value pairs, and you can have subcollections within documents. Firestore supports complex queries and provides features like atomic transactions and offline support

2.3 Choosing the right database for your project

To choose the right database for your project, consider the following factors:
Data structure: If your data is hierarchical or has simple relationships, Realtime Database might be a better fit. If your data requires complex queries or has more intricate relationships, Firestore is the better choice
Query capabilities: Realtime Database supports basic queries, while Firestore supports more advanced querying, like compound and composite indexing.
Pricing: Realtime Database charges based on the amount of data stored, data transferred, and simultaneous connections. Firestore charges based on the number of reads, writes, and deletes, as well as data storage and network usage.
Scalability: Firestore offers better automatic scaling, while Realtime Database requires manual scaling by sharding data across multiple databases
Consider these factors when choosing between Firebase Realtime Database and Firestore for your Android application with Kotlin development.

Section 3: Creating Documents and Collections with Android Kotlin Code

3.1 Setting up Firebase in your Android project

To set up Firebase in your Android project, follow these steps:
Go to the Firebase console (https://console.firebase.google.com/) and create a new project.
Click on "Add Firebase to your Android app" and provide your package name.
Download the google-services.json file and place it in your Android project's app folder.
Add the required dependencies to your project-level and app-level build.gradle files.
// Project-level build.gradlebuildscript { dependencies { classpath 'com.google.gms:google-services:4.3.10' }}

// App-level build.gradledependencies { implementation 'com.google.firebase:firebase-firestore-ktx:23.0.3'}
apply plugin: 'com.google.gms.google-services'

3.2 Creating a Firestore instance

To create a Firestore instance, use the following Kotlin code:
val firestore = FirebaseFirestore.getInstance()

3.3 Creating collections and documents using Kotlin code

You can create collections and documents using the following Kotlin code:
// Creating a new collectionval coursesCollection = firestore.collection("Courses")
// Creating a new documentval courseDocument = coursesCollection.document("Course1")

3.4 Example: Adding a collection for "Courses" and a document for each course

To add a collection for "Courses" and a document for each course, use this Kotlin code:
data class Course(val title: String, val instructor: String, val duration: Int)
fun addCourse(course: Course) { val coursesCollection = firestore.collection("Courses") val courseDocument = coursesCollection.document() courseDocument.set(course)}

Section 4: CRUD Operations with Android Kotlin Code


4.1 Introduction to CRUD operations in Firebase
CRUD operations (Create, Read, Update, Delete) are essential for managing data in Firebase. This section demonstrates examples of CRUD operations using Kotlin code.
4.2 Reading data using Kotlin code
To read data from Firestore, use the following Kotlin code:
fun getCourses(callback: (List<Course>) -> Unit) { firestore.collection("Courses").get() .addOnSuccessListener { documents -> val courses = documents.map { it.toObject<Course>() } callback(courses) }}


4.3 Example: Retrieving a list of courses from the "Courses" collection

getCourses { courses -> courses.forEach { course -> Log.d("Courses", "Course Title: ${course.title}, Instructor: ${course.instructor}, Duration: ${course.duration}") }}

4.4 Creating data using Kotlin code
Refer to the addCourse function in section 3.4 for creating data.

4.5 Example: Adding a new course to the "Courses" collection
val newCourse = Course("Android Development", "John Doe", 30)addCourse(newCourse)

4.6 Updating data using Kotlin code
To update data in Firestore, use the following Kotlin code:

fun updateCourse(courseId: String, updatedCourse: Course) { firestore.collection("Courses").document(courseId).set(updatedCourse)}

4.7 Example: Updating a course's details in the "Courses" collection

val updatedCourse = Course("Advanced Android Development", "Jane Smith", 45)val courseId = "Course1"updateCourse(courseId, updatedCourse)

4.8 Deleting data using Kotlin code
To delete data from Firestore, use the following Kotlin code:

fun deleteCourse(courseId: String) { firestore.collection("Courses").document(courseId).delete()}

4.9 Example: Removing a course from the "Courses" collection

val courseIdToDelete = "Course1"
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.