Android 项目 数据库
源码
配置
gradle/libs.versions.toml
[versions]
room = "2.8.4"
ksp = "2.3.5"
[libraries]
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
[plugins]
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
room = { id = "androidx.room", version.ref = "room" }
app/build.gradle.kts
plugins {
alias(libs.plugins.ksp)
alias(libs.plugins.room)
}
room { schemaDirectory("$projectDir/schemas") }
dependencies {
implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx)
ksp(libs.androidx.room.compiler)
}
AppDatabase
package cn.com.xuxiaowei.data
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
/** @see Database.version 数据库版本,当表结构发生变化时,数字 +1 */
@Database(entities = [AppOpen::class], version = 1, exportSchema = true)
abstract class AppDatabase : RoomDatabase() {
abstract fun appOpenDao(): AppOpenDao
companion object {
@Volatile private var Instance: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return Instance
?: synchronized(this) {
Room.databaseBuilder(context, AppDatabase::class.java, "app_database")
.fallbackToDestructiveMigration(false)
.build()
.also { Instance = it }
}
}
}
}
AppOpen
package cn.com.xuxiaowei.data
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "app_open")
data class AppOpen(@PrimaryKey(autoGenerate = true) val id: Long = 0, val openedAt: Long)
AppOpenDao
package cn.com.xuxiaowei.data
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
@Dao
interface AppOpenDao {
@Insert suspend fun insert(event: AppOpen)
@Query("SELECT COUNT(*) FROM app_open") suspend fun count(): Long
}
RepoDbProvider
package cn.com.xuxiaowei.data.db
import android.content.Context
object RepoDbProvider {
fun init(context: Context) {}
}
App
package cn.com.xuxiaowei
import android.app.Application
import android.os.Build
import cn.com.xuxiaowei.data.AppDatabase
import cn.com.xuxiaowei.data.AppOpen
import cn.com.xuxiaowei.data.db.RepoDbProvider
import cn.com.xuxiaowei.service.MinuteTaskService
import cn.com.xuxiaowei.utils.FileLogger
import cn.com.xuxiaowei.worker.FifteenMinuteWorker
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
class App : Application() {
private val applicationScope: CoroutineScope by lazy {
CoroutineScope(SupervisorJob() + Dispatchers.IO)
}
override fun onCreate() {
super.onCreate()
RepoDbProvider.init(this)
val appVersion =
try {
val pm = packageManager
val pi = pm.getPackageInfo(packageName, 0)
val versionName = pi.versionName ?: "unknown"
val versionCode =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
pi.longVersionCode.toString()
} else {
@Suppress("DEPRECATION") pi.versionCode.toString()
}
"$versionName($versionCode)"
} catch (e: Exception) {
"unknown"
}
val deviceInfo = "model=${Build.MODEL}, brand=${Build.BRAND}, sdk=${Build.VERSION.SDK_INT}"
FileLogger.log(this, "startup", "App", "App started version=$appVersion, $deviceInfo")
applicationScope.launch {
val db = AppDatabase.getDatabase(this@App)
db.appOpenDao().insert(AppOpen(openedAt = System.currentTimeMillis()))
val count = db.appOpenDao().count()
FileLogger.log(this@App, "startup", "App", "App open count=$count")
}
MinuteTaskService.start(this)
FifteenMinuteWorker.schedule(this)
}
}
效果