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

Room数据库初始化失败及代码引用错误求助

解决Android Room数据库引用错误及创建问题

问题说明

在Android项目中使用Room数据库时,数据库无法自动创建且执行函数失败,同时CarManagerFragment中出现两个未解析引用错误:

  • file:///C:/Users/Megaport/AndroidStudioProjects/ProgettoOfficina2/app/src/main/java/com/example/progettoofficina2/CarManagerFragment.kt:39:23 Unresolved reference: getDatabase
  • file:///C:/Users/Megaport/AndroidStudioProjects/ProgettoOfficina2/app/src/main/java/com/example/progettoofficina2/CarManagerFragment.kt:40:21 Unresolved reference: carDao

相关代码

CarManagerFragment代码

class CarManagerFragment : Fragment() {
    //initialize the needed variables
    private lateinit var db : Database
    private lateinit var carDao: CarDao
    private lateinit var etPlate: EditText
    ...
    private lateinit var btnCarAdd: Button
    private lateinit var rvCars: RecyclerView

    //creates the view with the onclicklistener
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_car_manager, container, false)

        //initialize the variables
        db = Database.getDatabase(requireContext())
        carDao = db.carDao()
        etPlate = view.findViewById(R.id.etPlate)
        ...
        etOwner = view.findViewById(R.id.etOwner_id)
        btnCarAdd = view.findViewById(R.id.btnAdd_car)
        rvCars = view.findViewById(R.id.rvCars)

        //show all the cars in the listview
        rvCars.adapter = CarAdapter(carDao.getAll())
        
        btnCarAdd.setOnClickListener {

            //create a new car
            val car = Car(
                plate = etPlate.text.toString(),
                ...
                year = etYear.text.toString().toInt(),
                owner = etOwner.text.toString()
            )

            //insert the car in the database
            carDao.insert(car)

        }
        return view
    }
}

Dao类代码

@Dao
interface CarDao {
    @Query("SELECT * FROM car")
    fun getAll(): List<Car>

    @Query("SELECT * FROM car WHERE id IN (:carIds)")
    fun loadAllByIds(carIds: IntArray): List<Car>

    @Query("SELECT * FROM car WHERE owner = :owner")
    fun loadAllByOwner(owner: Int): List<Car>

    @Query("SELECT * FROM car WHERE plate = :plate")
    fun loadByPlate(plate: String): Car

    @Insert
    abstract fun insert(car: Car)

    @Delete
    fun delete(car: Car)

    @Update
    fun update(car: Car)

}

@Dao
interface CustomerDao {
    @Query("SELECT * FROM customer")
    fun getAll(): List<Customer>

    @Query("SELECT * FROM customer WHERE id IN (:customerIds)")
    fun loadAllByIds(customerIds: IntArray): List<Customer>

    @Query("SELECT * FROM customer WHERE name = :name AND surname = :surname")
    fun loadByNameAndSurname(name: String, surname: String): Customer

    @Insert
    abstract fun insert(customer: Customer)

    @Delete
    fun delete(customer: Customer)

    @Update
    fun update(customer: Customer)

}

@Dao
interface InterventionDao {
    @Query("SELECT * FROM intervention")
    fun getAll(): List<Intervention>

    @Insert
    fun insert(intervention: Intervention)

    @Delete
    fun delete(intervention: Intervention)

    @Update
    fun update(intervention: Intervention)
}

数据库类代码

@Database(entities = [Customer::class, Car::class, Intervention::class], version = 1)
abstract class Database : RoomDatabase() {
    abstract fun customerDao(): CustomerDao
    abstract fun carDao(): CarDao
    abstract fun interventionDao(): InterventionDao

    companion object {
        @Volatile
        private var INSTANCE: Database? = null

        fun getDatabase(context: Context): Database {
            val tempInstance = INSTANCE
            if (tempInstance != null) {
                return tempInstance
            }
            synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    Database::class.java,
                    "database"
                ).build()
                INSTANCE = instance
                return instance
            }
        }
    }
}

修复方案

1. 解决类名冲突(核心问题)

自定义的Database类与Android系统自带的android.database.Database类重名,导致编译器无法识别自定义类。将自定义数据库类重命名为AppDatabase:

修改后的数据库类:

@Database(entities = [Customer::class, Car::class, Intervention::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun customerDao(): CustomerDao
    abstract fun carDao(): CarDao
    abstract fun interventionDao(): InterventionDao

    companion object {
        @Volatile
        private var INSTANCE: AppDatabase? = null

        fun getDatabase(context: Context): AppDatabase {
            val tempInstance = INSTANCE
            if (tempInstance != null) {
                return tempInstance
            }
            synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "app_database"
                ).build()
                INSTANCE = instance
                return instance
            }
        }
    }
}

同时更新CarManagerFragment中的引用:

private lateinit var db : AppDatabase
// ...
db = AppDatabase.getDatabase(requireContext())

2. 确认导入语句正确

确保CarManagerFragment中导入了自定义的AppDatabase和CarDao:

import com.example.progettoofficina2.AppDatabase
import com.example.progettoofficina2.CarDao

3. 检查Room依赖配置

在Module级别的build.gradle中确认添加了Room的完整依赖:

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'kotlin-kapt' // 必须添加,用于编译Room注解
}

dependencies {
    def room_version = "2.5.0" // 使用最新稳定版本
    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
    // 若使用协程,添加KTX扩展
    implementation "androidx.room:room-ktx:$room_version"
}

4. 移除非主线程数据库操作

Room禁止在主线程执行数据库操作,否则会抛出异常。改用协程处理:

在CarManagerFragment中添加协程作用域,并修改数据库操作:

class CarManagerFragment : Fragment() {
    private val scope = CoroutineScope(Dispatchers.IO + Job())
    // ...

    override fun onCreateView(...) {
        // ...
        // 异步加载数据并更新UI
        scope.launch {
            val cars = carDao.getAll()
            withContext(Dispatchers.Main) {
                rvCars.adapter = CarAdapter(cars)
            }
        }

        btnCarAdd.setOnClickListener {
            val car = Car(
                plate = etPlate.text.toString(),
                year = etYear.text.toString().toInt(),
                owner = etOwner.text.toString()
            )
            // 异步插入数据并刷新列表
            scope.launch {
                carDao.insert(car)
                val updatedCars = carDao.getAll()
                withContext(Dispatchers.Main) {
                    (rvCars.adapter as? CarAdapter)?.updateData(updatedCars)
                }
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        scope.cancel() // 销毁时取消协程,避免内存泄漏
    }
}

同时给CarAdapter添加刷新数据的方法:

class CarAdapter(private var carList: List<Car>) : RecyclerView.Adapter<CarAdapter.CarViewHolder>() {
    // ...
    fun updateData(newCars: List<Car>) {
        carList = newCars
        notifyDataSetChanged()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 09:12:05