Android 仅在ViewModel中切换线程
安卓工作室4 RxJava2,MVVM 方法#1 在我的活动中:Android 仅在ViewModel中切换线程,android,retrofit2,rx-java2,Android,Retrofit2,Rx Java2,安卓工作室4 RxJava2,MVVM 方法#1 在我的活动中: val dispose = filmsRxJavaViewModel.filmsListSingle .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnSubscribe( {// call before .doOnTerminate()
val dispose = filmsRxJavaViewModel.filmsListSingle
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe( {// call before .doOnTerminate()
Debug.d(TAG, "initLogic: doOnSubscribe:")
binding.progressBarLayout.containerProgressBarLayout.setVisibility(View.VISIBLE)
})
.doOnTerminate({// call before .subscribe()
Debug.d(TAG, "initLogic: doOnTerminate:")
binding.filmsSwipeRefreshLayout.isRefreshing = false
binding.progressBarLayout.containerProgressBarLayout.setVisibility(View.GONE)
})
// Only after call subscribe() then execute network request
.subscribe({ filmsList -> // success
Debug.d(TAG, "initLogic: subscribe: success")
// Hide swipe to refresh icon animation
if (filmsList.size > 0) { // list<Film>
filmItemListDataBindingAdapter!!.updateData(filmsList)
} else {
binding.filmsRecyclerView.visibility = View.GONE
binding.emptyLayoutContainer.root.visibility = View.VISIBLE
}
}, {// error
throwable ->
Debug.e(TAG, "initLogic: subscribe: error = $throwable")
Toast.makeText(this, throwable.message, Toast.LENGTH_LONG).show()
})
正如您所看到的,我将在线程之间切换到viewModel
我认为这是一个正确的方法。只有viewModel必须需要在线程之间切换。因此,我的活动仅适用于视图小部件(如ShowToast)
这是正确的方法吗?将沉重的Rx逻辑放在ViewModel中才是正确的方法 这是为了可测试性:片段和活动很重,很难测试。相比之下,ViewModel易于测试 因此,我们按照模式使片段和活动“愚蠢” 片段和活动应该只观察ViewModel的模型(这是一包原语)的更改。这是由公开LiveData的ViewModel完成的。对于视图的瞬时更改(如Toast),片段或活动可以观察处理时过期的事件流的LiveData 请查看Android架构蓝图和
SingleLiveEvent
而且,它们不是RxJava中的“线程”——它们是调度器
class FilmsRxJavaViewModel(application: Application) : AndroidViewModel(application) {
companion object {
private val TAG = FilmsRxJavaViewModel::class.java.name
}
lateinit var filmsListSingle: Single<List<Film>>
init {
Debug.d(TAG, "init:")
loadData()
}
fun loadData() {
Debug.d(TAG, "loadData:")
filmsListSingle = TransportServiceRxJava.getFilms()
}
}
fun getFilms() : Single<List<Film>> {
return testRxJavaRestClient.getFilms()
}
import io.reactivex.Single
import retrofit2.http.GET
interface TestRxJavaRestClient {
@GET("films")
fun getFilms(): Single<List<Film>>
}
val dispose = filmsRxJavaViewModel.filmsListSingle
.doOnSubscribe( {// call before .doOnTerminate()
Debug.d(TAG, "initLogic: doOnSubscribe:")
binding.progressBarLayout.containerProgressBarLayout.setVisibility(View.VISIBLE)
})
.doOnTerminate({// call before .subscribe()
Debug.d(TAG, "initLogic: doOnTerminate:")
binding.filmsSwipeRefreshLayout.isRefreshing = false
binding.progressBarLayout.containerProgressBarLayout.setVisibility(View.GONE)
})
// Only after call subscribe() then execute network request
.subscribe({ filmsList -> // success
Debug.d(TAG, "initLogic: subscribe: success")
// Hide swipe to refresh icon animation
if (filmsList.size > 0) { // list<Film>
filmItemListDataBindingAdapter!!.updateData(filmsList)
} else {
binding.filmsRecyclerView.visibility = View.GONE
binding.emptyLayoutContainer.root.visibility = View.VISIBLE
}
}, {// error
throwable ->
Debug.e(TAG, "initLogic: subscribe: error = $throwable")
Toast.makeText(this, throwable.message, Toast.LENGTH_LONG).show()
})
fun loadData() {
Debug.d(TAG, "loadData:")
filmsListSingle = TransportServiceRxJava.getFilms()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}