向ROOM数据库写入数据时App崩溃:如何初始化UserDatabase?
解决kotlin.UninitializedPropertyAccessException:lateinit属性userDB未初始化的问题
错误日志:
2022-08-03 15:41:29.243 21219-21250/com.example.roomdatabasetest E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1 Process: com.example.roomdatabasetest, PID: 21219 kotlin.UninitializedPropertyAccessException: lateinit property userDB has not been initialized at com.example.roomdatabasetest.MainActivity$writeData$1.invokeSuspend(MainActivity.kt:52) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
问题原因:
你声明了lateinit var userDB : UserDatabase,但在调用userDB.userDao().insertAll(user)前未对其初始化,导致抛出未初始化异常。
初始化UserDatabase的步骤:
1. 确认UserDatabase类的正确定义
你的UserDatabase必须是Room数据库的抽象类,带有@Database注解,示例如下:
import androidx.room.Database import androidx.room.RoomDatabase @Database(entities = [User::class], version = 1) abstract class UserDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
2. 用单例模式管理数据库实例(推荐)
为避免重复创建数据库连接,给UserDatabase添加单例实现:
@Database(entities = [User::class], version = 1) abstract class UserDatabase : RoomDatabase() { abstract fun userDao(): UserDao companion object { @Volatile private var INSTANCE: UserDatabase? = null fun getDatabase(context: Context): UserDatabase { return INSTANCE ?: synchronized(this) { val instance = Room.databaseBuilder( context.applicationContext, // 使用全局上下文避免内存泄漏 UserDatabase::class.java, "user_database" // 数据库文件名 ).build() INSTANCE = instance instance } } } }
3. 在MainActivity中初始化userDB
修改onCreate方法,添加初始化代码:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) btnWriteData = findViewById(R.id.btnWriteData) btnReadData = findViewById(R.id.btnReadData) etFirstName = findViewById(R.id.etFirstName) etLastName = findViewById(R.id.etLastName) // 初始化userDB userDB = UserDatabase.getDatabase(this) btnWriteData.setOnClickListener{ writeData() } btnReadData.setOnClickListener{ readData() } }
额外提示:
- 首次创建数据库存在IO耗时,
Room.databaseBuilder().build()允许在主线程调用,但正式环境建议在IO协程中初始化;测试阶段可临时添加allowMainThreadQueries(),但不推荐用于生产环境 - 使用
applicationContext初始化数据库,避免Activity销毁引发的内存泄漏
内容的提问来源于stack exchange,提问作者Clivityy
相关产品推荐
相关产品推荐

