Room Database in Android
Overview
Room database is a persistence library of Android Jetpack. It is used to deal with database operations efficiently. It provides and abstraction layer over SQLite.
Steps to follow
Dependencies
def room_version = "2.4.0"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
def coroutine_version = "1.6.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"
def lifecycle_version = "2.4.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
Updated Dependencies
/* Room Database */
implementation "androidx.room:room-runtime:2.4.3"
implementation "androidx.room:room-ktx:2.4.3"
kapt "androidx.room:room-compiler:2.4.3"
/* To add list into a Room Entity */
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1"
/* Room Database with Paging */
implementation "androidx.room:room-paging:2.4.3"
Entities
It is a table within a database. You have to use the annotation @Entity to mark the data class as a table. The properties of the class are the columns of the table.
Annotations used in an entity class
- @Entity: e.g. @Entity(tableName = "users")
- @PrimaryKey: @PrimaryKey(autoGenerate = true)
- @ColumnInfo: @ColumnInfo(name = “column_name”)
- @Ignore
- @Embedded
e.g.
@Entity(tableName = "contact")
data class Contact(
@PrimaryKey(autoGenerate = true) val id : Long ,
val name : String ,
val phone : String ,
val createdDate : Date ,
val isActive : Int
)
Dao
Dao stands for Data access objects. It is an interface where you can define the methods that you are going to use for the database. You have to use the annotation @Dao to mark the interface as Dao.
@Dao
interface ContactDao
{
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertContact(contact : Contact)
@Update
suspend fun updateContact(contact : Contact)
@Delete
suspend fun deleteContact(contact : Contact)
@Query("SELECT * from contact")
fun getContacts() : LiveData<List<Contact>>
}
Database
This is the actual database that you are going to use for Room Database. It's actually an abstract class which is extended by RoomDatabase class. You have to use the annotation @Database to mark the abstract class as Database. You can create database with the help of two methods databaseBuilder() or inMemoryDatabaseBuilder(). If you want to add Date in your table then you have to use @TypeConverters. And in future if you want to add columns in your existing table then you have to use the object of Migration.
@Database(entities = [Contact::class] , version = 2)
@TypeConverters(Converter::class)
abstract class ContactDatabase : RoomDatabase()
{
abstract fun contactDao() : ContactDao
companion object
{
val migration2_1 = object : Migration(
1 , 2
)
{
override fun migrate(database : SupportSQLiteDatabase)
{
database.execSQL("ALTER TABLE contact ADD COLUMN isActive INTEGER NOT NULL DEFAULT(1)")
}
}
/* Informs the entire thread that the value of a variable (e.g. INSTANCE) is updated */
@Volatile
private var INSTANCE : ContactDatabase? = null
fun getDatabase(context : Context) : ContactDatabase
{
if (INSTANCE == null)
{
synchronized(this) {
INSTANCE =
Room.databaseBuilder(context , ContactDatabase::class.java , "ContactDB")
.addMigrations(
migration2_1
).build()
}
}
/* returning a non-nullable INSTANCE */
return INSTANCE !!
}
}
}
class Converter
{
@TypeConverter
fun fromDateToLong(value : Date) : Long
{
return value.time
}
@TypeConverter
fun fromLongToDate(value : Long) : Date
{
return Date(value)
}
}
Use the instance of Database in Activity or Fragment
class MainActivity : AppCompatActivity()
{
companion object
{
const val TAG = "MainActivity"
}
private lateinit var database : ContactDatabase
override fun onCreate(savedInstanceState : Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
database = ContactDatabase.getDatabase(this)
MainScope().launch {
database.contactDao()
.insertContact(Contact(0 , "Raaj Kanchan" , "7718881920" , Date() , 1))
}
}
fun getData(view : android.view.View)
{
database.contactDao().getContacts().observe(this , Observer {
Log.d(TAG , "getData :: SQLiteData : ${it.toString()}")
})
}
}
Converters for using List in Room Database
Code:
import androidx.room.TypeConverter
import com.shawinfosolutions.astaguru.model.ArrImageFilePathItem
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
class Converters {
@OptIn(kotlinx.serialization.ExperimentalSerializationApi::class)
@TypeConverter
fun fromList(value: List<ArrImageFilePathItem?>) = Json.encodeToString(value)
@OptIn(kotlinx.serialization.ExperimentalSerializationApi::class)
@TypeConverter
fun toList(value: String) = Json.decodeFromString<List<ArrImageFilePathItem?>>(value)
}
Room vs SQLite
- Queries of Room Database is verified at compile time whereas queries of SQLite is not verified at compile time.
- Room Database can be used with LiveData or RxJava but SQLite cannot be used with them.
- Room Database converts queries to Java data objects without any boilerplate codes, but SQLite requires a lot of boilerplate codes to do the same job.
- When you change the schema of a table then you have to change the affected queries in SQLite manually. But you don't have to do the same when you use Room Database.
Do's and Dont's
- Caution - Room version 2.4.0 causes error when you are using syncrhonized() and Room.databuilder() methods
- Caution - Do not declare any query functions as suspend in the Dao interface.
References
- https://blog.mindorks.com/introduction-to-room-persistent-library-in-android
- https://medium.com/mindorks/using-room-database-android-jetpack-675a89a0e942
- https://medium.com/androiddevelopers/using-and-testing-room-kotlin-apis-4d69438f9334
- https://developer.android.com/training/data-storage/room
- https://developer.android.com/training/data-storage/room/defining-data
Comments
Post a Comment