In fact, Room depends on the use of library, I believe that you as long as a simple look at the official document on the use of Room this article, soon can be integrated through. However, because it is relatively simple and not technically difficult, it is not worth wasting too much time. Therefore, friends who have not tried access can follow my article to learn more about it. I’ll keep a brief note of all the holes I’ve stepped in.

First, the use of dependency libraries

Refer to the official Google documentation for dependencies

// This implementation has some exceptions for Kotlin
dependencies {
    def room_version = "2.3.0"

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"
}
Copy the code

For the modular structure of subsequent applications, we created a new Android Module and created this dependency in the child Module

A. Stomp pit 1 — Dependency properties of child Module

Refer to the article: The Difference between API and Implementation to recall the exception problem with child Mododule references. We need to change the implementation reference to the API reference, otherwise the APP module that references this submodule will not be able to access the related classes because of hidden dependencies.

B. Annotation 2 — Add kapt and replace annotationProcessor

See a related issue on StackOverflow – AppDatabase_Impl does not exist. The dependency provided in the official documentation of consciousness does not take into account kotlin’s replacement, requiring the above dependency to be replaced with Kapt

Also, to use Kapt, remember to add a plugin

C. Final implementation

plugins {
    ...
    id 'kotlin-kapt'}... dependencies {// Rely on room lib
    def room_version = "2.3.0"
    api "androidx.room:room-runtime:$room_version"
    kapt  "androidx.room:room-compiler:$room_version"
}
Copy the code

Create room entity class and database class

Room has made a good encapsulation of SQL. As long as we use it normally according to the official documents, we do not need to write complicated SQL statements by ourselves. For details, we refer to the official documents to learn the following

First, create the Entity class Entity (let’s start with a simple Person class)

/ * * *@author Lucius Ren
 * @since2021/9/1 21:33 * * Database entity class - person holds basic information about each person */
@Entity(tableName = "person")
data class Person(
    @PrimaryKey val uidNum: Long.@ColumnInfo(name = "full_name") valfullName: String? .@ColumnInfo(name = "first_name") valfirstName: String? .@ColumnInfo(name = "last_name") vallastName: String? .@ColumnInfo(name = "sex") val sex: Int? .// 0 for unknown, 1 for male, 2 for female
)
Copy the code

Next, use this Entity to create the relevant Dao abstraction interface (after adding the relevant annotations, the concrete implementation is automatically generated, which feels similar to the direction of greenDao)

/ * * *@author Lucius Ren
 * @since2021/9/1 21:42 * * Corresponds to the Dao interface */ of the Person table
@Dao
interface PersonDao {
    @Query("SELECT * FROM person")
    fun getAll(a): List<Person? >@Query("SELECT * FROM person WHERE uidNum IN (:userIds)")
    fun loadAllByIds(userIds: LongArray): List<Person? >@Query(
        "SELECT * FROM person WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1"
    )
    fun findByName(first: String, last: String): Person?

    @Query(
        "SELECT * FROM person WHERE full_name LIKE :fullName LIMIT 1"
    )
    fun findByFullName(fullName: String): Person?

    @Insert
    fun insertAll(vararg users: Person)

    @Delete
    fun delete(user: Person)
}
Copy the code

Step 3: Create the Database Abstract class (again, with annotations, the concrete implementation is generated)

/ * * *@author Lucius Ren
 * @since2021/9/1 21:33 * * Database class used by APP */
@Database(entities = [Person::class], version = 1)
abstract class LuciusTowerDatabase: RoomDatabase() {
    abstract fun personDao(a): PersonDao
}
Copy the code

Step 4: Create Util to initialize database access:

/ * * *@author Lucius Ren
 * @since2021/9/1 22:04 * * Use singleton mode to access the util */ of the database
object LuciusTowerDatabaseUtil {
    const val DATABASE_NAME_LUCIUS_TOWER = "lucius-tower"

    var db: LuciusTowerDatabase? = null

    fun initDatabase(context: Context) {
        db = Room.databaseBuilder(
            context, LuciusTowerDatabase::class.java, DATABASE_NAME_LUCIUS_TOWER
        ).allowMainThreadQueries().build()
    }
}
Copy the code

5. Finally, initialize the database in onCreate() of your application (if your application does not need to initialize it initially, you can consider calling it where you need to).

override fun onCreate(a) {
    super.onCreate()
    // ...
    // 2. Initialize database
    LuciusTowerDatabaseUtil.initDatabase(this)}Copy the code

Three, self-test database related code

After the relevant code is added, add a page to do a simple self-test.

// Todo Lucius removes debug code
private fun insertPerson(a) {
    Log.d(TAG, "insertPerson")
    try{ LuciusTowerDatabaseUtil.db? .personDao()? .insertAll(Person(123456L."LuciusRen"."Lucius"."Ren".1))}catch (e: Throwable) {
        Log.e(TAG, "insertPerson get error: $e")}}private fun checkPersonSex(a) {
    valperson = LuciusTowerDatabaseUtil.db? .personDao()? .findByFullName("LuciusRen")
    valsex = person? .sex Log.d(TAG,"person = $person, sex = $sex")

    valpeopleList = LuciusTowerDatabaseUtil.db? .personDao()? .getAll() Log.d(TAG,"personList = ${peopleList? .size},")}Copy the code

Click the test button to call the two methods, and get the following log:

The 2021-09-09 16:41:06. 362, 22470-22470 / com. Lucius. Luciustower D/MainActivity: InsertPerson 16:41:09. 2021-09-09, 365, 22470-22470 / com. Lucius. Luciustower D/MainActivity: person = Person(uidNum=123456, fullName=LuciusRen, firstName=Hongfei, lastName=Ren, sex=1), sex = 1Copy the code

Four, summary

At this point, our access is basically completed. For more complex configuration and use, refer to a follow-up article on the Goole website – Defining data with Room Entities, etc.

That’s the end of this article. This is enough to meet basic development persistent storage needs.

If we still need to improve the new customization method, we will open a new article and make it into a unified column, so that I can come back to introspection later.

Five, reference:

  1. Room use details and common database comparison – compare the database performance and so on, can give you decide whether to replace tradeoff, do a simple reference