如何处置以前的请求并停止观察以前的实时数据



>我正在尝试实现一个具有搜索视图的应用程序,当用户搜索某些内容时,应用程序将调用返回可观察数据的改造请求。在myRepository中,我将可观察量转换为可流动量,在myViewModel中,我将可移动量转换为LiveData,我在myActivity中观察到这些数据。

但问题是,如果用户搜索不止一次并且非常快(在获得上一个结果之前(,那么我想取消以前的请求,也不想观察以前的数据。

所以我使用的代码如下所示:

主活动

class MainActivity  : DaggerAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
observeRepos()
}
fun getReposFromServer(filter_search :String )    {
mainViewModel.getReposFromServer(filter_search)    }
private fun observeRepos() {
mainViewModel.observeReposFromServer().observe(this, Observer { repos ->
txtVwCount.setText("total item count is: "+repos?.total_count.toString())
})
mainViewModel.observeItemList().observe(this, Observer {
if(!it.isNullOrEmpty())
if(it.size>0) {
mAdapter.setReposInAdapter(it)
progressBar.visibility = View.GONE
}
})
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
.....
......
searchView.setOnQueryTextListener(object: SearchView.OnQueryTextListener{
override fun onQueryTextSubmit(query: String?): Boolean {
query?.let {
if(it.trim().length>0) {
clearOldCalls()
getReposFromServer(it,"","")      }
}
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
return false;          }
})
return true
}

fun clearOldCalls()   {
mainViewModel.clearRetrofitCall()
mAdapter.clearListInAdapter() //in my adapter I just make the list empty by assigning a new list to it
}
}

主视图模型:

class MainViewModel @Inject constructor() : ViewModel() {
var liveGitResult = MediatorLiveData<GitResult>()
val liveItemList =  MediatorLiveData<MutableList<ItemList>>()
@set:Inject
lateinit var mainRepository: MainRepository
fun getReposFromServer(filter_search: String)    {
val resultFromApiCall_flowable : Flowable<GitResult> =  mainRepository.fetchToDosFromServer(filter_search)
lateinit var source: LiveData<GitResult>
resultFromApiCall_flowable.let { 
source = LiveDataReactiveStreams.fromPublisher(it)
liveGitResult.addSource(source) { todos ->
liveGitResult.setValue(todos)
liveGitResult.removeSource(source)   }
}
var itemList_observable = resultFromApiCall_flowable.map {//it = gitResult
gitResult ->
var lst = mutableListOf<ItemList>()
gitResult.items.forEach {
lst.add(it)   }
lst
}
itemList_observable?.let{
var liveItemList  = LiveDataReactiveStreams.fromPublisher(itemList_observable)
this.liveItemList.addSource(liveItemList){ itemList ->
this.liveItemList.setValue(itemList)
this.liveItemList.removeSource(liveItemList)    }
}

fun observeReposFromServer(): LiveData<GitResult> {
return liveGitResult
}
fun observeItemList(): LiveData<MutableList<ItemList>> {
return liveItemList
}
fun clearRetrofitCall()
{
liveGitResult.value =null
liveItemList.value = null
mainRepository.clearDisposables()
}
}

主存储库:

class MainRepository @Inject constructor(mainApi: MainApi) {
private val mainApi: MainApi
private val disposables: CompositeDisposable = CompositeDisposable()

init {
this.mainApi = mainApi
}
fun fetchToDosFromServer(filter_search: String) : Observable<GitResult> {
lateinit var  returnedData : Observable<GitResult>
//mainApi.getAllRepo(filter_search) is a retrofit call which returns a   Flowable<GitResult>
returnedData =    mainApi.getAllRepo(filter_search).subscribeOn( Schedulers.io())
.onErrorReturn(Function {throwable ->
Log.e( LOG_TAG, "Something went wrong" )
null
})

returnedData.subscribeOn(Schedulers.io())
.observeOn( AndroidSchedulers.mainThread())
.subscribe(object :Observer<GitResult>{
override fun onSubscribe(d: Disposable) {
disposables.add(d)  }
override fun onComplete() { }
override fun onNext(t: GitResult) { }
override fun onError(e: Throwable) { }
})
return returnedData.toFlowable(BackpressureStrategy.BUFFER);
}

fun clearDisposables(){
if(disposables!=null){
if(!disposables.isDisposed)
disposables.clear()
disposables.dispose()
}
}
}

现在,如果我运行该应用程序并在获得先前的结果之前非常快速地搜索多次 - 那么它的行为很奇怪。

  • 它逐个显示回收器视图中的所有结果。之前的结果不应该被处理掉,并且它们不会转换为实时数据吗?
  • 也不是按顺序调用它们
  • 此外,不会同时显示回收器视图数据和文本视图数据,可能使用来自不同 Livedata 源的观察者

那么,我哪里做错了?

还有如何在单个语句中编写returnedData代码,而不是将其编写在我正在执行的 2 个语句中(一个用于调用 api,另一个用于覆盖订阅方法(。

对于类似的情况,我保留了一堆一次性用品,并在启动新订阅时处理最旧的订阅。我在它们中运行 OkHtttp 请求,所以在处理时,它们被打断了。

当用户在上一个请求仍在进行时创建另一个请求时取消以前的改造请求,您可以使用 Kotlin 的协程来实现此目的。

您可以使用暂停函数启动协程,该函数调用您的 api 请求并保持在启动协程时返回的"Job"对象的引用,当您的用户在上一个请求正在进行时发送另一个搜索请求时,您只需使用 'job.isActive' 检查上一个改造请求是否正在进行中,如果它处于活动状态,那么您可以调用 'job.cancel((' 停止观察以前的 liveData 和开始新作业。

class MainViewModel @Inject constructor() : ViewModel() {
// Job instance
private var job = Job()
fun requestApiForResponse(val searchQuery:String){
if(job?.isActive) // check if any previous job is running , if true then cancel that 
job?.cancel()
job = GlobalScope.launch(Dispatchers.IO){
//call your retrofit Request here
}
}
override fun onCleared() {
super.onCleared()
job.cancel()
}
}

使用实时数据和协程检查此 github 的存储库搜索功能

相关内容

  • 没有找到相关文章

最新更新