学习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
相关产品推荐
相关产品推荐

