Ali*_*tar 1 android rx-android retrofit2
在我的应用程序中,我请求json填充recyclerview,它在init int kotlin viewmodel中的第一个总是成功,但是当我想再次在timer.schedule方法中请求时,它转到一次性订阅中的onError方法,这是Edittext的onTextChange绑定在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()
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的请求方法:
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)
}
Run Code Online (Sandbox Code Playgroud)
这是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)
}
Run Code Online (Sandbox Code Playgroud)
我该怎么办 ?
小智 5
您最初在ViewModel初始化中对loadMovies的调用来自main / ui线程。timertask对loadMovies的调用来自后台线程。现在我对rx没有太多的经验,但是问题似乎仍然与livedata有关。
您正在观察主线程,这对于成功方法和错误方法都很好。您的问题似乎是从backround线程调用的onRetrieveMoviesListStart()和onRetrieveMoviesListFinish()。
只能从主线程调用livedata值的设置器,要从后台线程设置值,则需要调用postValue。
像这样更改两个方法/函数应该可以解决问题:
private fun onRetrieveMoviesListStart() {
loadingVisibility.postValue(View.VISIBLE)
Timber.d("started")
}
private fun onRetrieveMoviesListFinish() {
loadingVisibility.postValue(View.GONE)
Timber.d("finished")
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
864 次 |
| 最近记录: |