You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Room onCreate回调+Hilt初始化数据时出现OverlappingFileLockException异常

解决Room+Hilt初始化数据时的OverlappingFileLockException异常

问题原因

你在Room的onCreate回调里直接调用了provideDatabase()方法,这会创建一个全新的AppDatabase实例。此时正在创建的原数据库实例已经持有了数据库文件的锁,新实例又尝试获取同一个文件的锁,直接触发了java.nio.channels.OverlappingFileLockException。

正确解决方案

方案1:直接用回调提供的SupportSQLiteDatabase执行SQL

不需要创建新的数据库实例,直接通过回调传入的SupportSQLiteDatabase执行插入操作,避免锁冲突:

@Singleton
@Provides
fun provideDatabase(@ApplicationContext applicationContext: Context): AppDatabase {
    return Room.databaseBuilder(applicationContext, AppDatabase::class.java, DATABASE_NAME)
        .allowMainThreadQueries()
        .fallbackToDestructiveMigration()
        .addCallback(object : RoomDatabase.Callback() {
            override fun onCreate(db: SupportSQLiteDatabase) {
                super.onCreate(db)
                // 替换成你的user表实际字段和LocalUser对应的值
                db.execSQL(
                    "INSERT INTO user (username, email) VALUES (?, ?)",
                    arrayOf("default_user", "default@example.com")
                )
            }
        })
        .build()
}

方案2:用Hilt注入Dao做初始化(更符合架构规范)

把初始化逻辑抽成单独的类,通过Hilt注入Dao,在App启动时执行初始化,同时避免重复插入:

// 数据初始化类
class DatabaseInitializer @Inject constructor(private val userDao: UserDao) {
    fun initData() {
        // 先检查是否已有数据,防止重复初始化
        if (userDao.getTotalUsers() == 0) {
            userDao.createUser(LocalUser())
        }
    }
}

// 数据库提供方法去掉回调
@Singleton
@Provides
fun provideDatabase(@ApplicationContext applicationContext: Context): AppDatabase {
    return Room.databaseBuilder(applicationContext, AppDatabase::class.java, DATABASE_NAME)
        .allowMainThreadQueries()
        .fallbackToDestructiveMigration()
        .build()
}

// 在Application中触发初始化
@HiltAndroidApp
class MyApplication : Application() {
    @Inject
    lateinit var dbInitializer: DatabaseInitializer

    override fun onCreate() {
        super.onCreate()
        dbInitializer.initData()
    }
}

为什么无Hilt的教程能正常运行

无Hilt场景下,一般会通过单例模式确保全局只有一个数据库实例,初始化时要么直接操作原始数据库连接,要么复用已有的单例实例,不会出现多个实例同时抢占文件锁的情况,所以不会触发这个异常。

内容的提问来源于stack exchange,提问作者Pavel Poley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 17:12:49