[go: up one dir, main page]

0% found this document useful (0 votes)
29 views32 pages

Lecture 8 (Part 2)

The document provides a comprehensive overview of implementing a Room database in Android, detailing the creation of a Database Class, handling migrations, and utilizing Auto Migrations. It also discusses the Repository Pattern for managing data sources, emphasizing the benefits of using Flow with Room for automatic updates and asynchronous execution. Additionally, it outlines the integration of ViewModel with the Repository for efficient data handling and separation of concerns.

Uploaded by

ukr.droid.dev
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
29 views32 pages

Lecture 8 (Part 2)

The document provides a comprehensive overview of implementing a Room database in Android, detailing the creation of a Database Class, handling migrations, and utilizing Auto Migrations. It also discusses the Repository Pattern for managing data sources, emphasizing the benefits of using Flow with Room for automatic updates and asynchronous execution. Additionally, it outlines the integration of ViewModel with the Repository for efficient data handling and separation of concerns.

Uploaded by

ukr.droid.dev
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 32

Room.

LocalDataSource

Author:Semen Naduiev
Quick reminder
Database Class and Migrations in Room

The Database Class is the central component of the Room database. It serves as the main entry
point for database interactions and manages database configuration, versioning, and migrations.
Defining a Room Database Class

To create a Room database, you need to define an abstract class that extends RoomDatabase.
This class should be annotated with @Database, specifying:

The entities (tables) that belong to this database.

The database version.

Whether it should be exported for schema versioning.


@Database(entities = [...], version =
X): Defines the tables (entities) and
database version.

abstract class AppDatabase :


RoomDatabase(): The main database
class must extend RoomDatabase

abstract fun userDao(): UserDao: DAO


methods should be defined to provide
access to the database.

Room.databaseBuilder(context,
AppDatabase::class.java, "db_name"):
Initializes the database.
Handling Database Migrations in Room

When you update your database schema (e.g., add/remove columns or tables), you need to handle
migrations to prevent data loss.

Why Use Migrations?

Ensures data is preserved when updating the app.

Prevents users from having to reinstall the app to get the new schema.

Room enforces version control, so migrations are required when schema changes.
Example: Migration from Version 1 to Version 2
Now, in version 2, we want to add an email column.

Let's say in version 1, we had a simple User table:


Handling Multiple Migrations

If you're moving from version 1 → 2 → 3, you need multiple migrations.

For example, if in version 3, we add a notes table:


Auto Migrations in Room

Auto Migration in Room automates schema migrations when upgrading the database without
writing SQL migration scripts manually.

✅ Key Benefits:

● No manual SQL: Room automatically detects schema changes.


● Less error-prone: Reduces migration-related bugs.
● Easier maintenance: Room handles most common schema modifications.
Enabling Auto Migrations in Room

To use Auto Migrations, you must:

● Set up a Room Database class with @Database annotation.


● Define the new version.
● Specify autoMigrations in the @Database annotation.
Handling Complex Auto Migrations

Auto Migrations work only for simple schema changes (adding/removing columns, tables,
foreign keys).

For complex migrations, you need to:

● Use @RenameColumn to rename columns.


● Use @RenameTable to rename tables.
● Provide custom migrations when required.
Using @RenameColumn (Column Renaming)

By default, Room does NOT support renaming columns directly.

To rename a column in Auto Migration, use @RenameColumn.


Using @RenameTable (Table Renaming)
Combining Auto and Manual Migrations in Room
Step 3: Manual Migration (Version 3 - Changing email Type)

Auto migration cannot change column types. We need a manual migration.


Using DB in ViewModel
Використання у Activity
Alternative

Using Android ViewModel(not the best, but good temporary)


Creating Application Class
To use AndroidViewModel you need to create and application class. It’s a start point of your app
and just a singleton.

To add it create a class that inherits from Application() class.


Add android:name to the Manifest file
Combining Flow and Room in Android

Why Use Flow with Room?

Automatic Updates: When data in the database changes, the Flow will emit the updated values.

Asynchronous Execution: Flow runs on a background thread, avoiding UI freezes.

Efficient Data Handling: Flow cancels previous emissions when a new update comes, reducing
unnecessary work.
Defining a DAO with Flow
Using Flow in the Repository
Observing Data in ViewModel
Introduction to Repository Pattern

The Repository Pattern is used to manage data sources in a structured way.

It abstracts the data layer and provides a clean API for the rest of the app.

Helps in separating concerns and enables easier testing.


Why Use the Repository Pattern?

Decouples data sources from business logic.

Provides a single source of truth.

Facilitates switching between local and remote data sources.

Simplifies testing by enabling mock repositories.


Structure of the Repository Pattern

Repository: Acts as a mediator between ViewModel and data sources.

Remote Data Source: Fetches data from an API.

Local Data Source: Stores data in a database or cache.


Implementation of a Repository

class UserRepository(

private val remoteDataSource: UserRemoteDataSource,

private val localDataSource: UserLocalDataSource

){

suspend fun getUser(userId: String): User {

return localDataSource.getUser(userId) ?: remoteDataSource.getUser(userId).also {

localDataSource.saveUser(it)

}
Integration with ViewModel

class UserViewModel(private val userRepository: UserRepository) : ViewModel() {

private val _user = MutableStateFlow<User>()

val user: StateFlow<User> get() = _user.asStateFlow()

fun loadUser(userId: String) {

viewModelScope.launch(Dispatchers.IO) {

_user.value = userRepository.getUser(userId)

}
Repository Pattern

You might also like