preface

Room is officially a persistent repository that provides an abstraction layer on SQLite, powerful and reliable SQL object mapping capabilities, and support for LiveData and RxJava.

Add the following dependencies to your project

    def room_version = "2.1.0 - alpha04"
    def lifecycle_version = "2.0.0"
    def rxjava_version = '2.1.7'
    def rxandroid_version = '2.1.0'
    // Room
    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
    implementation "androidx.room:room-rxjava2:$room_version"
    // RxJava
    implementation "io.reactivex.rxjava2:rxjava:$rxjava_version"
    implementation "io.reactivex.rxjava2:rxandroid:$rxandroid_version"
    // ViewModel and LiveData
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    implementation 'com. Google. Code. Gson: gson: 2.8.5'// check the database implementation'com. Facebook. Stetho: stetho - okhttp3:1.5.0'
Copy the code

When data is queried asynchronously, the returned object can be either a LiveData or Flowable. Such as:

    @Query("SELECT * FROM user")
    abstract fun getAllUsers(a): Flowable<List<User>>

    @Query("SELECT * FROM user")
    abstract fun getAllUser(a): LiveData<List<User>>
Copy the code

When we store an Entity class that contains a List, we define an Entity in the normal way. The following error is reported when compiling:

Cannot figure out how to save this field into database. You can consider adding a type converter for it.
Copy the code

This is because Room cannot store data of type List directly, which we will address next.

practice

  • Given that a User object has many favorite books, the Entity class is typically defined in the following format:

    
    @Entity(tableName = "user")
    data class User(
    
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "id")
        val id: Int.@ColumnInfo(name = "name")
        val name: String,
    
        @ColumnInfo(name = "books")
        val books: List<Book>
    
    )
    
    data class Book(
        val bookName: String
    )
    Copy the code
  • In the current case, compiling the project will encounter the error mentioned earlier. We can convert any object with @typeconverter. For example, define a BookConverters

    class BookConverters {
    
        @TypeConverter
        fun stringToObject(value: String): List<Book> {
            val listType = object : TypeToken<List<Book>>() {
    
            }.type
            return Gson().fromJson(value, listType)
        }
    
        @TypeConverter
        fun objectToString(list: List<Book>): String {
            val gson = Gson()
            return gson.toJson(list)
        }
    }
    Copy the code
  • Add the @Typeconverters annotation to the entity class

    @Entity(tableName = "user")
    @TypeConverters(BookConverters::class)
    data class User(
    
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "id")
        val id: Int.@ColumnInfo(name = "name")
        val name: String,
    
        @ColumnInfo(name = "books")
        val books: List<Book>
    
    )
    
    data class Book(
        val bookName: String
    )
    
    Copy the code

@TypeConverters

The purpose of this annotation is to tell Room what additional type converters are available.

Converters are generally defined in a fixed format:

class AnyConverters {

    @TypeConverter
    fun stringToObject(value: String): List<Any> {
        val listType = object : TypeToken<List<Any>>() {

        }.type
        return Gson().fromJson(value, listType)
    }

    @TypeConverter
    fun objectToString(list: List<Any>): String {
        val gson = Gson()
        return gson.toJson(list)
    }
}
Copy the code

Using Facebook’s Stetho, you can easily view the contents of your database:

Code sample

The resources

Stackoverflow official documentation