Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/219.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 仅在ViewModel中切换线程_Android_Retrofit2_Rx Java2 - Fatal编程技术网

Android 仅在ViewModel中切换线程

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()

安卓工作室4

RxJava2,MVVM

方法#1

在我的活动中:

 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())
    }