首页 > 解决方案 > 这些参数与注入的调度程序有什么不同?

问题描述

这两种方法调用相同的用例。在第一个版本中,我对 进行了硬编码Dispatchers.IO,并且事情按预期工作。

第二个版本(我更喜欢)使用默认Dispatchers.IO类型的注入调度程序。它因注释中描述的 IllegalStateException 而失败。有任何想法吗?

@HiltViewModel
class MainViewModel @Inject constructor(
    private val getUsers: GetUsers,
    private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
) : ViewModel() {
    val liveData: MutableLiveData<List<User>> = MutableLiveData()

    suspend fun getUsersByParamDispatcher(params: GetUsers.Params) {
        // Successfully works as intended.
        viewModelScope.launch(Dispatchers.IO) {
            getUsers(params).collectLatest {
                liveData.postValue(it)
            }
        }
    }

    suspend fun getUsersByInjectDispatcher(params: GetUsers.Params) {
        // IllegalStateException: Cannot access database on the main thread since it may potentially
        // lock the UI for a long period of time.
        //   at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:494).
        viewModelScope.launch(dispatcher) {
            getUsers(params).collectLatest {
                liveData.postValue(it)
            }
        }
    }
}

日志确认了异常,我的好奇心是它们为什么不同,以及我将如何获得有效的注入版本。

注入 Dispatchers.IO 失败:

>> coroutine.name: main

工作参数 Dispatchers.IO:

>> coroutine.name: DefaultDispatcher-worker-1

依赖项由提供@HiltViewModel,我希望调度程序尊重其分配的默认值。by viewModels()Fragment 使用委托创建此视图模型。

对调度程序进行硬编码可能很好。但是通过注入,TestCoroutineDispatcher在测试期间很容易通过阻塞。

也许我忽略了一些简单的东西,或者完全是另一种方式。

// MainViewModelTest
@Before
fun setup() {
    MockKAnnotations.init(this)

    viewModel = MainViewModel(
        getUsers,
        coroutinesTestRule.testDispatcher
    )
}

标签: androidkotlindagger-2kotlin-coroutinesdagger-hilt

解决方案


推荐阅读