以MVI模式提供或发送频道的正确位置 [英] Right place to offer or send Channel in MVI pattern
问题描述
我预先将数据加载到recycleView中.为了做到这一点,我在Activity的onCreate()中有以下代码:
I load data in recycleView in advance. In order to do that I have following code in onCreate() of Activity :
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupUI()
setupViewModel()
observeViewModel()
if (savedInstanceState == null) {
mainViewModel.userIntent.offer(MainIntent.FetchUser)
}
}
当saveInstanceState为null时,您看到我 offer()
,问题是当我们发生进程死亡时(您可以通过激活不将活动保留在开发人员中"选项来简单地创建它),重新加载数据将不会被触发.
As you see I offer()
when savedInstanceState is null, The problem is when we have process death ( you can simply create it by activating Do not keep activities in developer option), reload of data will not be triggered.
另一种选择是在ViewModel的 init
块中使用它,但是问题是我想进行波纹管单元测试,可以验证所有三种状态:
another option is to use it inside init
block of ViewModel, but problem is I want to have bellow unit test which I can verify all three states :
@Test
fun givenServerResponse200_whenFetch_shouldReturnSuccess() {
runBlockingTest {
`when`(apiService.getUsers()).thenReturn(emptyList())
val apiHelper = ApiHelperImpl(apiService)
val repository = MainRepository(apiHelper)
val viewModel = MainViewModel(repository)
viewModel.state.asLiveData().observeForever(observer)
viewModel.userIntent.send(MainIntent.FetchUser)
}
verify(observer, times(3)).onChanged(captor.capture())
verify(observer).onChanged(MainState.Idle)
verify(observer).onChanged(MainState.Loading)
verify(observer).onChanged(MainState.Users(emptyList()))
}
如果在ViewModel初始化后立即使用init块选项,则会调用 send
或 offer
,而未使用 observeForever
以上单元测试中的LiveData.
If I use the init block option as soon as ViewModel initialized, send
or offer
will be called while observeForever
did not be used for LiveData in the above unit test.
这是我的ViewModel类:
Here is my ViewModel class :
class MainViewModel(
private val repository: MainRepository
) : ViewModel() {
val userIntent = Channel<MainIntent>(Channel.UNLIMITED)
private val _state = MutableStateFlow<MainState>(MainState.Idle)
val state: StateFlow<MainState>
get() = _state
init {
handleIntent()
}
private fun handleIntent() {
viewModelScope.launch {
userIntent.consumeAsFlow().collect {
when (it) {
is MainIntent.FetchUser -> fetchUser()
}
}
}
}
private fun fetchUser() {
viewModelScope.launch {
_state.value = MainState.Loading
_state.value = try {
MainState.Users(repository.getUsers())
} catch (e: Exception) {
MainState.Error(e.localizedMessage)
}
}
}
}
以上情况的解决方案是什么?
What could be the solution for the above scenarios?
推荐答案
我发现的唯一解决方案是将 fetchUser
方法和另一个 _state
作为MutableStateFlow移至存储库层,并在存储库中 observeForever
进行本地单元测试,因此我可以在ViewModel的init块中发送或提供 userIntent
.
The only solution that I found is moving fetchUser
method and another _state
as MutableStateFlow to Repository layer and observeForever
it in Repository for local unit test, as a result I can send or offer userIntent
in init block off ViewModel.
在ViewModel中,我将具有以下 _state
:
I will have following _state
in ViewModel :
val userIntent = Channel<MainIntent>(Channel.UNLIMITED)
private val _state = repository.state
val state: StateFlow<MainState>
get() = _state
这篇关于以MVI模式提供或发送频道的正确位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!