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

学习Hilt时无法从Room数据库打印查询数据,寻求技术帮助

问题:Room查询数据无法在控制台打印,无任何输出

我在学习Hilt开发项目,需要对Room数据库执行CRUD操作,已经插入了部分数据,但调用查询后控制台没有任何输出,无法看到查询到的数据。

以下是相关代码:

DAO

@Dao
interface EmployeeDAO {
    @Query("SELECT * FROM employees")
    fun getEmployees(): Flow<EmployeeModel>
}

仓库接口

interface EmployeeRepository {
    suspend fun getEmployees(): Flow<EmployeeModel>
}

仓库实现类

class RepositoryImplementation @Inject constructor(
    private val employeeDAO: EmployeeDAO): EmployeeRepository {

    override suspend fun getEmployees(): Flow<EmployeeModel> {
        return employeeDAO.getEmployees()
    }
}

ViewModel

@HiltViewModel
class EmployeeViewModel @Inject constructor(
    private val repository: dagger.Lazy<EmployeeRepository>
) : ViewModel() {

    suspend fun getEmployees() = viewModelScope.launch {
        repository.get().getEmployees().collect{
            println("TEST: ${it.name}")
        }
    }
}

Fragment

@AndroidEntryPoint
class ManageEmployees : Fragment() {
    private var _binding: FragmentManageEmployeesBinding? = null
    private val mBinding get() = _binding!!
    private val mViewModel: EmployeeViewModel by activityViewModels()
    @Inject
    lateinit var repo: EmployeeRepository

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentManageEmployeesBinding.inflate(inflater, container, false)
        val view = mBinding.root

        viewLifecycleOwner.lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                mViewModel.getEmployees()
            }
        }
        return view
    }
}

仓库模块

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {

    @Binds
    @Singleton
    abstract fun bindRepository(
        repositoryImplementation: RepositoryImplementation
    ): EmployeeRepository
}

数据库模块

@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {

    @Singleton
    @Provides
    fun createDatabase(
        @ApplicationContext context: Context
    ) = Room.databaseBuilder(
        context,
        EmployeeDatabase::class.java,
        "employee_database"
    ).build()

    @Singleton
    @Provides
    fun provideDAO(database: EmployeeDatabase): EmployeeDAO{
        return database.getDAO()
    }
}

问题排查与修复方案

1. 修正DAO查询返回类型

SELECT * FROM employees查询的是所有员工记录,应该返回Flow<List<EmployeeModel>>而非Flow<EmployeeModel>。单个EmployeeModel无法匹配多条数据,会导致Flow无法正常发射数据。

修正后的DAO:

@Dao
interface EmployeeDAO {
    @Query("SELECT * FROM employees")
    fun getEmployees(): Flow<List<EmployeeModel>>
}

2. 同步修改仓库接口与实现类

仓库的返回类型必须和DAO保持一致:

仓库接口

interface EmployeeRepository {
    suspend fun getEmployees(): Flow<List<EmployeeModel>>
}

仓库实现类

class RepositoryImplementation @Inject constructor(
    private val employeeDAO: EmployeeDAO
) : EmployeeRepository {

    override suspend fun getEmployees(): Flow<List<EmployeeModel>> {
        return employeeDAO.getEmployees()
    }
}

3. 调整ViewModel的数据收集逻辑

由于返回类型变为集合,需要遍历集合打印每个员工数据,同时移除不必要的suspend修饰:

@HiltViewModel
class EmployeeViewModel @Inject constructor(
    private val repository: dagger.Lazy<EmployeeRepository>
) : ViewModel() {

    fun getEmployees() = viewModelScope.launch {
        repository.get().getEmployees().collect { employees ->
            employees.forEach { employee ->
                println("TEST: ${employee.name}")
            }
        }
    }
}

4. 优化Fragment的生命周期绑定

使用Lifecycle.State.STARTED替代CREATED,确保Fragment处于可见状态时才执行数据收集,避免生命周期不一致导致的问题:

viewLifecycleOwner.lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        mViewModel.getEmployees()
    }
}

5. 验证Room数据与查询执行

添加Room查询日志,确认数据是否存在、查询是否执行:

@Singleton
@Provides
fun createDatabase(
    @ApplicationContext context: Context
) = Room.databaseBuilder(
    context,
    EmployeeDatabase::class.java,
    "employee_database"
)
    .fallbackToDestructiveMigration()
    .setQueryCallback(object : QueryCallback {
        override fun onQuery(sqlQuery: String, bindArgs: List<Any?>) {
            println("Room Query: $sqlQuery, Args: $bindArgs")
        }
    }, Executors.newSingleThreadExecutor())
    .build()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 08:35:04