如何实现带参数的Room查询及对应Repository、ViewModel层逻辑
实现逻辑说明
非LiveData类型的Room同步查询为阻塞操作,禁止在主线程直接调用,必须在后台线程执行,以下是Repository与ViewModel层的完整实现方案:
1. Repository层实现
Kotlin版本
class MemberRepository(private val memberDao: MemberDao) { // 协程实现:挂起函数自动切IO线程执行查询 suspend fun getPlayersForReselection(reselectedPlayerName: String): List<Member> { return withContext(Dispatchers.IO) { memberDao.getPlayersForReselection(reselectedPlayerName) } } // 回调实现:适合不使用协程的场景,自动切回主线程返回结果 fun getPlayersForReselectionAsync(reselectedPlayerName: String, callback: (List<Member>) -> Unit) { Executors.newSingleThreadExecutor().execute { val result = memberDao.getPlayersForReselection(reselectedPlayerName) Handler(Looper.getMainLooper()).post { callback(result) } } } }
Java版本
public class MemberRepository { private final MemberDao memberDao; private final ExecutorService executor = Executors.newSingleThreadExecutor(); private final Handler mainHandler = new Handler(Looper.getMainLooper()); // 定义结果回调接口 public interface PlayerQueryCallback { void onQueryResult(List<Member> playerList); } public MemberRepository(MemberDao memberDao) { this.memberDao = memberDao; } public void getPlayersForReselection(String reselectedPlayerName, PlayerQueryCallback callback) { executor.execute(() -> { // 后台线程执行查询 List<Member> result = memberDao.getPlayersForReselection(reselectedPlayerName); // 切回主线程返回结果 mainHandler.post(() -> callback.onQueryResult(result)); }); } }
2. ViewModel层实现
Kotlin版本
class MemberViewModel(private val repository: MemberRepository) : ViewModel() { // 使用viewModelScope自动管理协程生命周期,避免内存泄漏 fun loadReselectPlayers(name: String, onResult: (List<Member>) -> Unit) { viewModelScope.launch { val playerList = repository.getPlayersForReselection(name) // 已自动回到主线程,可直接传递给UI层使用 onResult(playerList) } } }
提示:使用
viewModelScope需要引入KTX扩展依赖:implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2"
Java版本
public class MemberViewModel extends ViewModel { private final MemberRepository repository; public MemberViewModel(MemberRepository repository) { this.repository = repository; } public void loadReselectPlayers(String name, MemberRepository.PlayerQueryCallback callback) { repository.getPlayersForReselection(name, callback); } }
注意事项
- 禁止直接在主线程调用DAO层的同步查询方法,Room默认会抛出主线程操作数据库的异常
- 如果项目使用RxJava,可直接将DAO方法返回值改为
Single<List<Member>>,Room原生支持RxJava类型返回值,无需手动处理线程切换
内容的提问来源于stack exchange,提问作者SteveC
相关产品推荐
相关产品推荐

