Using Room Persistence Library (Part of Jetpack) in Android Development
Room is an abstraction layer over SQLite, part of Jetpack, which allows for more robust database access while leveraging SQLite's full power. It provides a higher-level API for database operations and integrates seamlessly with Kotlin. This article will guide you on how to use Room for managing local databases in Android applications.
1. Adding Room Dependencies
To start using Room in your project, you need to add the necessary dependencies to your build.gradle file.
Example 1: Adding Room Dependencies
        dependencies {
            def room_version = "2.5.0"
            implementation "androidx.room:room-runtime:$room_version"
            annotationProcessor "androidx.room:room-compiler:$room_version"  // For Java
            kapt "androidx.room:room-compiler:$room_version"  // For Kotlin
        }
        
        2. Defining the Entity
In Room, an Entity represents a table in the database. Each field in the class corresponds to a column in the table. We need to annotate the data model with @Entity.
Example 2: Defining an Entity
    import androidx.room.Entity
    import androidx.room.PrimaryKey
    @Entity(tableName = "users")
    data class User(
        @PrimaryKey(autoGenerate = true) val id: Int = 0,
        val name: String,
        val age: Int
    )
        
        In this example:
- @Entityannotation defines the table "users" in the database.
- @PrimaryKeymarks the primary key for the table, with auto-generation for the ID.
3. Creating the DAO (Data Access Object)
The DAO is responsible for accessing the database. It contains methods to insert, update, delete, and query the database.
Example 3: Defining a DAO
    import androidx.room.Dao
    import androidx.room.Insert
    import androidx.room.Query
    @Dao
    interface UserDao {
        @Insert
        suspend fun insert(user: User)
        @Query("SELECT * FROM users")
        suspend fun getAllUsers(): List
        @Query("SELECT * FROM users WHERE id = :userId")
        suspend fun getUserById(userId: Int): User
    }
         
        In this example:
- @Daoannotation marks this interface as a DAO.
- @Insertis used to insert a user into the database.
- @Queryis used for custom SQL queries to retrieve users from the database.
4. Creating the Database
The RoomDatabase class serves as the main access point to the database. It provides the method to get a reference to the DAO.
Example 4: Creating Room Database
    import androidx.room.Database
    import androidx.room.RoomDatabase
    @Database(entities = [User::class], version = 1)
    abstract class AppDatabase : RoomDatabase() {
        abstract fun userDao(): UserDao
    }
        
        In this example:
- @Databaseannotation defines the entities and the database version.
- abstract fun userDao()method is used to get access to the UserDao for database operations.
5. Accessing the Database
Now that you have defined the Entity, DAO, and Database, you can access the database from your activity or any other component in your app. Room provides a simple and efficient way to get an instance of the database using the Room.databaseBuilder() method.
Example 5: Accessing Room Database in MainActivity
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import androidx.room.Room
    import kotlinx.coroutines.CoroutineScope
    import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.launch
    import kotlinx.coroutines.withContext
    class MainActivity : AppCompatActivity() {
        private lateinit var db: AppDatabase
        private lateinit var userDao: UserDao
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            // Initialize the database
            db = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "app_database")
                .build()
            userDao = db.userDao()
            // Insert a user into the database
            CoroutineScope(Dispatchers.IO).launch {
                val newUser = User(name = "John Doe", age = 25)
                userDao.insert(newUser)
                val users = userDao.getAllUsers()
                // Update UI on the main thread
                withContext(Dispatchers.Main) {
                    users.forEach { user ->
                        println("User: ${user.name}, Age: ${user.age}")
                    }
                }
            }
        }
    }
        
        In this example:
- We create an instance of AppDatabaseusingRoom.databaseBuilder().
- The database is accessed in a background thread using Kotlin Coroutines.
- Once the data is retrieved, it is updated on the main thread using withContext(Dispatchers.Main).
6. Conclusion
Room provides a powerful and efficient solution for working with databases in Android. It abstracts much of the boilerplate code required for using SQLite and integrates seamlessly with Kotlin and Jetpack components. By using Room, developers can easily manage local data storage with minimal effort.