文章目录
现在kotlin 是趋势,那必然就要用到协程,还有就是随着jetpack 的发力,带来了很多好用的库,比如今天提到Room,是一个类似greenDao的数据库。它不但支持kotlin协程/RxJava,还具备编译期检查,是非常友好的库。我们一起来看下,在项目中怎么使用。
1、创建一个kotlin项目,然后在app里面的build.gradle添加依赖:
plugins {
...
id 'kotlin-android-extensions'
id 'kotlin-kapt'
}
dependencies {
...
//room数据库
implementation "androidx.room:room-runtime:2.4.2"
kapt "androidx.room:room-compiler:2.4.2" // Kotlin 使用 kapt
implementation "androidx.room:room-ktx:2.4.2"//Coroutines support for Room 协程操作库
//lifecycle
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0'
}
此时,我们同步一下,开始运行项目。会报错:
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8
解决:将项目的jdk1.8 改成 jdk11。
接下来还有报错:
Can't determine type for tag '?attr/shapeAppearanceCornerSmall '
原因是material 的版本高了的问题。
implementation 'com.google.android.material:material:1.8.0'
解决:我们将material,改成1.6.0。项目就能正常运行了。
2、相关的类的创建
2.1创建数据库的实体类
通过在实体类上加注解@Entity,这样实体类就相当于是一张表
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize
@Parcelize
@Entity(tableName = "Student")
data class Student(
@PrimaryKey
var id: String,
var name: String
) : Parcelable
2.2创建实体类的Dao:
通过在Dao接口上加注解@Dao,就可以让dao轻松地完成增删改查。
另外可以将 suspend Kotlin 关键字添加到 DAO 方法中,用 Kotlin 协程功能,使这些方法成为异步方法。这样可确保不会在主线程上执行这些方法。
@Dao
interface StudentDao {
//通过@Insert 注解的onConflict 解决冲突(如果有老的数据存在则会进行替换,如果没有就插入)
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun putStudent(cacheBean: Student)
@Query("select * from Student where id =:id")
suspend fun getStudent(id: String): Student?
@Query("select * from Student")
suspend fun getAllStudent(): List?
@Delete
suspend fun delete(student: Student)
@Update(onConflict = OnConflictStrategy.REPLACE)
suspend fun update(student: Student)
}
2.3 创建数据库的类
创建一个类继承RoomDatabase,加注解@Database,轻松地建数据库和建表
import android.util.Log
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
//后续的数据库升级通过这个version来控制,exportSchema是否导出数据库的配置信息
@Database(entities = [Student::class], version = 2, exportSchema = false)
abstract class StudentDatabase : RoomDatabase() {
companion object {
var dataBase: StudentDatabase
val TAG = StudentDatabase::class.java.simpleName
init {
//如果databaseBuilder改为inMemoryDatabaseBuilder则创建一个内存数据库(进程销毁后,数据丢失)
dataBase = Room.databaseBuilder(MyApplication.getApplicationContext(), StudentDatabase::class.java, "db_user")
//数据库的操作是否允许在主线程中执行
.allowMainThreadQueries()
//数据库创建和打开后的回调,可以重写其中的方法
.addCallback(object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
Log.d(TAG, "onCreate: db_student")
}
})
//数据库升级异常之后的回滚
.fallbackToDestructiveMigration()
.build()
}
}
abstract fun getStudentDao(): StudentDao
2.4 创建一个MyApplication
通过它我们来获取context。
class MyApplication : Application() {
init {
instance = this
}
companion object {
private var instance: MyApplication? = null
fun getApplicationContext() : Context {
return instance!!.applicationContext
}
}
override fun onCreate() {
super.onCreate()
}
}
通过点击按钮,进行增删改查的操作。
增加数据:
btn_add.setOnClickListener {
lifecycleScope.launch {
val studentDao = StudentDatabase.dataBase.getStudentDao()
studentDao.putStudent(Student("101","小李"));
studentDao.putStudent(Student("102","小王"))
}
}
更改数据:
btn_update.setOnClickListener {
lifecycleScope.launch {
val studentDao = StudentDatabase.dataBase.getStudentDao()
val student = studentDao.update(Student("101","小陈"))
Log.d(TAG,student.toString());
}
}
删除数据:
btn_delete.setOnClickListener {
lifecycleScope.launch {
val studentDao = StudentDatabase.dataBase.getStudentDao()
val student = studentDao.delete(Student("101","小陈"))
Log.d(TAG,student.toString());
val students = studentDao.getAllStudent()
Log.d(TAG, "students: $students")
}
}
查询数据:
lifecycleScope.launch {
btn_query.setOnClickListener {
lifecycleScope.launch {
val studentDao = StudentDatabase.dataBase.getStudentDao()
val students = studentDao.getAllStudent()
Log.d(TAG, "students: $students")
}
}
备注:数据库的操作一定要放到子线程中,切不可在主线程中操作,虽然可以通过allowMainThreadQueries强制开启允许这么做,但这个是测试时用,实际项目中还是不要在主线程中操作数据库,避免遇到ANR问题
源码地址:https://github.com/shenshizhong/KotlinRoomDemo
1 、导入依赖, 同步
2 、创建一个实体类Student,加注解@Entity就相当于一张表
3 、创建一个接口StudentDao,加注解@Dao就可以完成增删改查
4 、创建抽象类继承RoomDatabase,加注解@Database,轻松地建数据库和建表
5 、通过数据库的实例获取dao,调用方法
如果对你有一点点帮助,那是值得高兴的事情。:)
我的csdn:http://blog.csdn.net/shenshizhong
我的简书:http://www.jianshu.com/u/345daf0211ad