Kotlin + 协程 + Room 结合使用

文章目录

  • 前言
  • 集成Room
  • 结合协程的使用
  • 总结
一、前言,

现在kotlin 是趋势,那必然就要用到协程,还有就是随着jetpack 的发力,带来了很多好用的库,比如今天提到Room,是一个类似greenDao的数据库。它不但支持kotlin协程/RxJava,还具备编译期检查,是非常友好的库。我们一起来看下,在项目中怎么使用。

二、集成Room

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

你可能感兴趣的:(kotlin,jetpack,kotlin,开发语言,android,android,jetpack)