我正在当前的Android应用程序中的多个片段之间共享一个ActivityScoped viewModel。
viewModel使用协程范围viewModelScope.launch{}
我的问题是,.launch{}
仅在调用拥有的ViewModel
onCleared()
方法之前有效。
这是ViewModel范围的协程应该工作的方式吗?
是否有一种方法可以用来“重置” viewModelScope,以便.launch {}在调用onCleared()方法之后起作用?
这里是我的代码::
片段
RxSearchView.queryTextChangeEvents(search)
.doOnSubscribe {
compositeDisposable.add(it)
}
.throttleLast(300, TimeUnit.MILLISECONDS)
.debounce(300, TimeUnit.MILLISECONDS)
.map { event -> event.queryText().toString() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { charactersResponse ->
launch {
viewModel.search(charactersResponse.trim())
}
}
。。。
override fun onDetach() {
super.onDetach()
viewModel.cancelSearch()
compositeDisposable.clear()
}
ViewModel
suspend fun search(searchString: String) {
cancelSearch()
if (TextUtils.isEmpty(searchString)) {
return
}
job = viewModelScope.launch {
repository.search(searchString)
}
}
fun cancelSearch() {
job?.cancelChildren()
}
。。。
override fun onCleared() {
super.onCleared()
repository.onCleared()
}
我在做什么错?
UPDATE
如果我将启动代码修改为此
job = GlobalScope.launch {
repository.search(searchString)
}
它解决了我的问题,但是这是达到我期望的结果的唯一方法吗?
我对GlobalScope
的印象是“不好”
repository.onCleared()
此方法不应属于存储库。
实际上,存储库不应是有状态的。
[如果您检查Google的样本the Repository creates a LiveData
that contains a Resource
,并且之所以有意义,是因为LiveData
(在此样本中为Resource
,但从语义上讲,这是同一件事)。
the actual data loading and caching mechanic is inside this resource, triggered byLiveData.onActive
片段不应该启动协同程序。它应该说类似
LiveData.onActive
还有
MediatorLiveData.addSource
然后使用ViewModel将>
.subscribe { charactersResponse -> launch { viewModel.search(charactersResponse.trim())
这就是ViewModel中应该有的所有内容,那么问题是“谁拥有协程范围”?这取决于何时应取消任务。
如果“不再观察”应该取消任务,那么取消任务应该是.subscribe {
viewModel.updateSearchText(charactersResponse.trim())
}
。
如果“不再观察但不再清除”应保留任务,则ViewModel的onCleared实际上应控制ViewModel内部的SupervisorJob,该工作将在override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java, factory)
viewModel.searchResults.observe(viewLifecycleOwner, Observer { results ->
searchAdapter.submitList(results)
})
}
中取消,并且class MyViewModel(
private val repository: MyRepository
): ViewModel() {
private val searchText = MutableLiveData<String>()
fun updateSearchText(searchText: String) {
this.searchText.value = searchText
}
val searchResults: LiveData<List<MyData>> = Transformations.switchMap(searchText) {
repository.search(searchText)
}
}
应该在该范围内启动,即仅当您将CoroutineScope传递给LiveData.onInactive()
方法时,才有可能。
onCleared()
这项工作吗?不确定,我实际上并不使用协程,但我认为应该使用。但是,此示例不处理LiveData中的
search
-ing操作,也不处理协程。
将cal设置为onCleared()之后,我的viewModelScoped cororoutine启动将停止执行