配置
//file:build.gradle(Module)
plugins {
...
id 'kotlin-kapt'
}
...
dependencies {
...
implementation 'androidx.room:room-runtime:2.4.2'
implementation "androidx.room:room-ktx:2.4.2"
kapt 'androidx.room:room-compiler:2.4.2'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
}
数据库配置
//创建数据实体类
@Entity(tableName = "details")
data class Detail(
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
val id: Int? = null,
var message: String = "",
var date: String = "2021/1/1",
var detailType: DetailType = DetailType()
)
//复杂数据
data class DetailType(
val name: String = "无",
val triad: Boolean = true
)
//由于数据库无法添加除了规定类型外的所有类型,要写一个转化器来指导数据库进行复杂数据的转化
class DetailTypeConverters {
@TypeConverter
fun stringToObject(value: String?): DetailType? {
val it = object : TypeToken<DetailType>() {}.type
return Gson().fromJson(value, it)
}
@TypeConverter
fun objectToString(value: DetailType?): String? {
val gson = Gson()
return gson.toJson(value)
}
}
@Dao
interface DetailDao {
@Query("SELECT * FROM details")
fun queryAll(): Flow<List<Detail>>
@Insert
fun insert(detail: Detail?)
@Query("DELETE FROM details")
fun deleteAll()
@Update
fun updata(detail: Detail)
@Delete
fun delete(detail: Detail)
//[Detail::class]为你创建的数据实体类
//@return Flow<List<Detail>> 配合 jetpack compose 可以在数据变化时自动更新ui
@RawQuery(observedEntities = [Detail::class])
fun execsql(query: SupportSQLiteQuery) : Flow<List<Detail>>
}
//@Database(entities = [Detail::class], version = 1)entities为数据类,数据结构变化时version要增加1
//@TypeConverters(DetailTypeConverters::class,...)指定复杂数据格式转换器,多个转换器之间用逗号隔开
@Database(entities = [Detail::class], version = 1)
@TypeConverters(DetailTypeConverters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun getDetailDao(): DetailDao
}
App
你可以创建一个继承于Application的应用类来长久持有数据库的引用,在程序的任何地方都可以用
App.db.getDetailDao()获取到数据库的Dao(注意:getDetailDao()根据你定义的接口名而定)
class App:Application() {
companion object {
lateinit var db: AppDatabase
@SuppressLint("StaticFieldLeak")
var sContext: Context? = null
}
override fun onCreate() {
super.onCreate()
sContext = this
db = Room
.databaseBuilder(sContext as App,AppDatabase::class.java,"db_details")
.build()
}
}
Activity
数据库的操作不能在ui线程进行,使用Thread {...}.star()对数据库进行操作
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val detailDao = App.db.getDetailDao()
val details = detailDao.execsql(
SimpleSQLiteQuery(
"SELECT * FROM details WHERE message='hello'", //获取messge为hello的数据
arrayOf()
)
).asLiveData()
setContent {
val detailsState = details.observeAsState(arrayListOf()) //获取状态监听
LazyColumn {
item {
Button(onClick = {
val detail = Detail(
message = "hello",
detailType = DetailType("666", false),
)
Thread {
detailDao.insert(detail)
}.start()
}) {
Text("+1")
}
}
item {
Button(onClick = {
finish()
}) {
Text(text = "finish")
}
}
items(detailsState.value) { it ->
Row(
Modifier.fillMaxWidth()
) {
Text(text = "${it.id} ${it.message}")
IconButton(onClick = {
Thread {
detailDao.delete(it)
}.start()
}) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = "删除"
)
}
}
}
}
}
}
}
参考文献
使用 Room 将数据保存到本地数据库 | Android 开发者 | Android Developers (google.cn)