Jetpack Room上手实践demo

一、问题背景

jetpeck+kotlin持续学习中,现在来学习一下room,简单来说,room是Google提供给我们的来操作sqlite数据库的库,来看看使用这个有何益处。

二、实现方案(基于kotlin语言)

话不多说,直接上代码

(1)在项目module的gradle文件中添加相应依赖如下:

plugins {
    id 'com.android.application'
    ...
    // 需要在次数增加kapt插件
    id 'kotlin-kapt'
}

dependencies {
    def room_version = "2.4.2"
    implementation "androidx.room:room-runtime:$room_version"
    // 使用kapt来引入注解处理器
    kapt "androidx.room:room-compiler:$room_version"
}

(2)定义数据实体

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey

/**
 * User实体类
 */
@Entity(tableName = User.TAB_NAME)
class User {
    companion object {
        const val TAB_NAME = "user"
        const val COLUMN_ID = "id"
        const val COLUMN_NAME = "name"
        const val COLUMN_AGE = "age"
    }


    /**
     * 主键,设置autoGenerate = true之后Room才会自动给id分配值(从1开始自增加)
     */
    @PrimaryKey(autoGenerate = true)

    @ColumnInfo(name = COLUMN_ID)
    var uId: Int = 0

    /**
     * 设置在数据库表中字段名称,如果不设置,默认就是当前的属性名
     */
    @ColumnInfo(name = COLUMN_NAME)
    var uName: String? = null

    @ColumnInfo(name = COLUMN_AGE)
    var uAge: Int = 0

    @Ignore
    var uSex: Int = 0
}

(3)使用 Room DAO 访问数据

import androidx.room.*

/**
 * UserDao数据访问类
 */
@Dao
interface UserDao {
    /**
     * 查询当前表中数据的总数
     */
    @Query("SELECT COUNT(*) FROM " + User.TAB_NAME)
    fun count(): Int

    /**
     * 插入单条数据.
     *
     * @param user 用户实体实例
     * @return rowId
     */
    @Insert
    fun insert(user: User): Long

    /**
     * 插入多条数据.
     *
     * @param users 用户实体实例集合
     * @return rowId list
     */
    @Insert
    fun insertList(users: List<User>): List<Long>

    /**
     * 更新单条数据.
     *
     * @param user 用户实体实例
     * @return 根据主键更新成功的行数
     */
    @Update
    fun update(user: User): Int

    /**
     * 更新多条数据.
     *
     * @param users 用户实体实例集合
     * @return 根据主键更新成功的行数,就是更新成功了多少行
     */
    @Update
    fun updateList(users: List<User>): Int

    /**
     * 删除一条数据。
     *
     * @param user 用户实体实例
     * @return 根据主键删除成功的行数
     */
    @Delete
    fun delete(user: User): Int

    /**
     * 根据指定id删除数据.
     *
     * 跟删除单条数据是一样的。
     */
    @Query("DELETE FROM " + User.TAB_NAME + " WHERE " + User.COLUMN_ID + " = :id")
    fun deleteById(id: Long): Int

    /**
     * 删除多条数据。
     *
     * @param users 用户实体实例集合
     * @return 根据主键删除成功的行数,就是删除成功了多少行
     */
    @Delete
    fun deleteList(users: List<User>): Int

    /**
     * 查询指定id的数据.
     *
     * @param id 指定需要查询数据的id
     * @return 返回查询的实体类
     */
    @Query("SELECT *FROM " + User.TAB_NAME + " WHERE " + User.COLUMN_ID + " = :id")
    fun selectById(id: Long): User

    /**
     * 查询user表中所有数据.
     *
     * @return 数据表中数据集合
     */
    @Query("SELECT *FROM " + User.TAB_NAME)
    fun selectAll(): List<User>
}

(4)定义数据库操作类

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase

/**
 * 数据库操作类
 */
@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class DeterminedDatabase : RoomDatabase() {
    companion object {
        private const val DB_NAME = "determined.db"

        @Volatile
        private var INSTANCE: DeterminedDatabase? = null

        fun getInstance(context: Context): DeterminedDatabase {
            return INSTANCE ?: synchronized(this) {
                return INSTANCE ?: buildDatabase(context).also {
                    INSTANCE = it
                }
            }
        }

        private fun buildDatabase(context: Context): DeterminedDatabase {
            return Room.databaseBuilder(context, DeterminedDatabase::class.java, DB_NAME).build()
        }
    }

    abstract fun userDao(): UserDao
}

(5)activity中使用数据类,操作数据库

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import java.util.concurrent.Executors

class RoomActivity : AppCompatActivity(), View.OnClickListener {
    companion object {
        private const val TAG = "RoomActivity"
    }

    private lateinit var btInsert: Button
    private lateinit var btUpdate: Button
    private lateinit var btQuery: Button
    private lateinit var btDelete: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_room)

        init()
    }

    private fun init() {
        btInsert = findViewById(R.id.btInsert)
        btUpdate = findViewById(R.id.btUpdate)
        btQuery = findViewById(R.id.btQuery)
        btDelete = findViewById(R.id.btDelete)

        btInsert.setOnClickListener(this)
        btUpdate.setOnClickListener(this)
        btQuery.setOnClickListener(this)
        btDelete.setOnClickListener(this)
    }

    override fun onClick(view: View?) {
        when (view?.id) {
            R.id.btInsert -> {
                insert()
            }
            R.id.btUpdate -> {
                update()
            }
            R.id.btQuery -> {
                query()
            }
            R.id.btDelete -> {
                delete()
            }
        }
    }

    private fun insert() {
        runData {
            val user = User()
            user.uName = "张三"
            user.uAge = 25
            val rowId = DeterminedDatabase.getInstance(this@RoomActivity).userDao().insert(user)
            Log.d(TAG, "rowId:: $rowId")
        }
    }

    private fun update() {
        runData {
            val user = User()
            user.uId = 1
            user.uName = "李四"
            user.uAge = 25
            val columnNum = DeterminedDatabase.getInstance(this@RoomActivity).userDao().update(user)
            Log.d(TAG, "columnNum:: $columnNum")
        }
    }

    private fun query() {
        runData {
            val list = DeterminedDatabase.getInstance(this@RoomActivity).userDao().selectAll()
            for (user in list) {
                Log.d(TAG, "user:: $user")
            }
        }
    }

    private fun delete() {
        runData {
            val user = User()
            user.uId = 1
            val columnNum = DeterminedDatabase.getInstance(this@RoomActivity).userDao().delete(user)
            Log.d(TAG, "columnNum:: $columnNum")
        }
    }

    private fun runData(runnable: Runnable) {
        Executors.newSingleThreadExecutor().execute(runnable)
    }
}

(6)使用到activity_room布局文件内容如下,很简单,添加了4个按钮:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <Button
        android:id="@+id/btInsert"
        android:text="插入"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btUpdate"
        android:text="更新"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btQuery"
        android:text="查询"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btDelete"
        android:text="删除"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

三、demo效果如下: image.png