MVVM RXAndroid Невозможно вызвать setValue в фоновом потоке - PullRequest
0 голосов
/ 02 января 2019

В моем приложении я запрашиваю json, чтобы заполнить программу повторного просмотра, сначала в init kotlin viewmodel это всегда успешно, но когда я хочу запросить снова в методе timer.schedule, он переходит к методу onError в одноразовой подписке, вотOnTextChange Edittext, который связан в представлении xml:

fun onSearchTextChanged(text: CharSequence) {
    if (text.isNotEmpty()) {
        if (myTimer != null) {
            myTimer!!.cancel()
        }

        myTimer = Timer()
        myTimer!!.schedule(object : TimerTask() {
            override fun run() {
                loadMovies(text.toString(), 1)
            }

        }, 1000)
    } else {
        if (myTimer != null) {
            myTimer!!.cancel()
        }
    }
}

и вот мои методы запроса:

fun loadMovies(searchText: String, pageNumber: Int) {
    subscription = searchApi.getSearch(API_KEY, searchText, pageNumber)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnSubscribe { onRetrieveMoviesListStart() }
        .doOnTerminate { onRetrieveMoviesListFinish() }
        .subscribe(
            { result -> onRetrieveMoviesListSuccess(result) },
            { err -> onRetrieveMoviesListError(err) })
}

private fun onRetrieveMoviesListStart() {
    loadingVisibility.value = View.VISIBLE
    Timber.d("started")
}

private fun onRetrieveMoviesListFinish() {
    loadingVisibility.value = View.GONE
    Timber.d("finished")
}

private fun onRetrieveMoviesListSuccess(search: Search) {
    Timber.d(search.toString())
    movieListAdapter.updateMoviesList(search.Search)
    movieEvent.value = MovieEvent.ANIMATE_RECYCLER
}

private fun onRetrieveMoviesListError(err: Throwable) {
    Timber.e(err)
}

И это объявление класса viewModel:

@Inject
lateinit var searchApi: SearchApi

val movieListAdapter: MovieListAdapter = MovieListAdapter()
private var myTimer: Timer? = null

private val movieEvent = SingleLiveEvent<MovieEvent>()
private lateinit var subscription: Disposable
val loadingVisibility: MutableLiveData<Int> = MutableLiveData()

init {
    loadMovies("someText", 1)
}

Чтоя должен сделать?

1 Ответ

0 голосов
/ 02 января 2019

Ваш первоначальный вызов loadMovies в инициализации ViewModel происходит из потока main / ui.Вызов loadMovies из timertask поступает из фонового потока.Теперь у меня нет особого опыта работы с rx, но проблема, похоже, в любом случае связана с aliveata.

Вы наблюдаете за основной темой, что хорошо для методов успеха и ошибок.Кажется, ваша проблема в onRetrieveMoviesListStart () и onRetrieveMoviesListFinish (), которые вызываются из фонового потока.

Сеттер для значения liveata может быть вызван только из основного потока, чтобы установить значение из фонанить, вам нужно вызвать postValue .

Изменение ваших двух методов / функций, как это должно сделать свое дело:

private fun onRetrieveMoviesListStart() { 
    loadingVisibility.postValue(View.VISIBLE)
    Timber.d("started")
} 
private fun onRetrieveMoviesListFinish() {
    loadingVisibility.postValue(View.GONE)
    Timber.d("finished")
}
...