Room的使用很简单,主要是一堆注解,以及理解下协程。
1.实体类
@Entity(tableName = "cipher")
data class Cipher(
@ColumnInfo(name = "name", defaultValue = "user")
var userName: String,
@ColumnInfo
var password: String,
) {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
var id: Long = 0
}
@Entity(tableName = "cipher")
声明这个实体类是一个表,表名cipher
@ColumnInfo(name = "name", defaultValue = "user")
列名,及默认值。不写默认就是名字了
@PrimaryKey(autoGenerate = true)
声明主键,自增。
需要注意的是,这里我把主键放在了类里面{},因为声明了自增了,没必要每次初始化对象的时候都带个id。
再一个需要注意的是,如果之前有数据,你就算把整个表的数据都删了,新增的id也会继续自增,不会恢复至0。(除非代码写)
2.Dao
@Dao
interface CipherDao {
@Query("SELECT * FROM cipher")
fun getCipherAll(): Flow<List<Cipher>?>
@Query("SELECT * FROM cipher WHERE name like :name LIMIT 1")
fun getCipher(name: String): Flow<List<Cipher>?>
@Insert(onConflict = OnConflictStrategy.REPLACE, entity = Cipher::class)
suspend fun insertCipher(vararg cipher: Cipher)
@Update
suspend fun updateCipher(cipher: Cipher)
@Delete
suspend fun deleteCipher(cipher: Cipher)
@Query("delete from cipher")
suspend fun deleteAll()
}
3.Repository
class CipherRepository(private val cipherDao: CipherDao) {
fun loadAllUser(): Flow<List<Cipher>?> {
return cipherDao.getCipherAll()
}
fun loadAllByName(name: String): Flow<List<Cipher>?> {
return cipherDao.getCipher(name)
}
suspend fun insertCipher(vararg cipher: Cipher) {
cipherDao.insertCipher(*cipher)
}
suspend fun updateCipher(cipher: Cipher) {
cipherDao.updateCipher(cipher)
}
suspend fun deleteAll() {
cipherDao.deleteAll()
}
}
4.Database的创建
@Database(entities = [Cipher::class], version = 1)
abstract class CipherRoomDatabase : RoomDatabase() {
abstract fun CipherDao(): CipherDao
class CipherDatabaseCallback(private val scope: CoroutineScope) : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
// INSTANCE?.let { database ->
// scope.launch {
// val cipherDao = database.CipherDao()
// }
// }
}
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
}
override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
super.onDestructiveMigration(db)
}
}
companion object {
private var INSTANCE: CipherRoomDatabase? = null
fun getDatabase(context: Context, scope: CoroutineScope): CipherRoomDatabase {
return INSTANCE
?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
CipherRoomDatabase::class.java,
"c_database"
).addCallback(
CipherDatabaseCallback(
scope
)
)
.build()
INSTANCE = instance
instance
}
}
}
}
基本的创建到这里就结束了,下面是使用部分。
Kotlin 推出了协程。这里简单一说要不没法用。。。
首先,Flow是异步的,数据库操作用Flow很香的。
方法名加suspend前缀,表示协程。但是你用suspend的方法,必须在suspend里执行。
协程 相关知识可以参考最后的链接。
所以最终调用的代码:
val applicationScope = CoroutineScope(SupervisorJob())
val database by lazy { CipherRoomDatabase.getDatabase(this, applicationScope) }
val respository by lazy { CipherRepository(database.CipherDao()) }
Activity实现CoroutineScope:
class MainActivity : AppCompatActivity(), CoroutineScope {
lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
val applicationScope = CoroutineScope(SupervisorJob())
val database by lazy { CipherRoomDatabase.getDatabase(this, applicationScope) }
val respository by lazy { CipherRepository(database.CipherDao()) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
job = Job()
loadDataFromUI()
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
/*
* 注意 coroutine builder 的 scope, 如果 activity 被销毁了或者该函数内创建的 Coroutine
* 抛出异常了,则所有子 Coroutines 都会被自动取消。不需要手工去取消。
*/
fun loadDataFromUI() = launch { // <- 自动继承当前 activity 的 scope context,所以在 UI 线程执行
val ioData = async(Dispatchers.IO) { // <- launch scope 的扩展函数,指定了 IO dispatcher,所以在 IO 线程运行
// 在这里执行阻塞的 I/O 耗时操作
// respository.deleteAll()
var loadAllUser = respository.loadAllUser().collect {
it?.forEach {
Log.d("123", it.toString().plus(" ").plus(it.id))
}
}
return@async loadAllUser
}
// 和上面的并非 I/O 同时执行的其他操作
val data = ioData.await() // 等待阻塞 I/O 操作的返回结果
// draw(data) // 在 UI 线程显示执行的结果
}
}
项目目录结构:
这只是个Demo哈,学习用的。很多地方也不严谨,跑通为主。
协程参考:https://blog.csdn.net/u011133887/article/details/98617852
|