Android 如何处理以前的请求并停止观察以前的LiveData

Android 如何处理以前的请求并停止观察以前的LiveData,android,rx-java2,android-livedata,Android,Rx Java2,Android Livedata,我正在尝试实现一个应用程序,其中我有一个searchView,当用户搜索某个东西时,应用程序将调用一个翻新请求,该请求返回一个可观察的数据。在myRepository中,我将可观察数据转换为可流动数据,在myViewModel中,我将可流动数据转换为我在myActivity中观察到的LiveData 但问题是,如果用户搜索不止一次而且速度非常快(在得到以前的结果之前),那么我想取消以前的请求,也不想观察以前的数据 因此,我使用的代码如下所示: main活动 class MainActivity

我正在尝试实现一个应用程序,其中我有一个searchView,当用户搜索某个东西时,应用程序将调用一个翻新请求,该请求返回一个可观察的数据。在myRepository中,我将可观察数据转换为可流动数据,在myViewModel中,我将可流动数据转换为我在myActivity中观察到的LiveData

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

因此,我使用的代码如下所示:

main活动

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
    }

}
MainViewModel:

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

}
class MainViewModel@Inject构造函数():ViewModel(){
var livegitsresult=MediatorLiveData()
val liveItemList=MediatorLiveData()
@设置:注入
lateinit var mainRepository:mainRepository
fun getReposFromServer(过滤器\搜索:字符串){
val resultfrompicall\u flowable:flowable=mainRepository.fetchToDosFromServer(筛选搜索)
lateinit变量源:LiveData
resultfrompicall_flowable.let{
source=LiveDataReactiveStreams.fromPublisher(it)
liveGitResult.addSource(源){todos->
liveGitResult.setValue(todos)
liveGitResult.removeSource(源)}
}
var itemList\u observable=resultfrompicall\u flowable.map{//it=gitsult
gitResult->
var lst=mutableListOf()
gitsresult.items.forEach{
lst.add(it)}
lst
}
可观察到的项目列表?让我们{
var liveItemList=LiveDataReactiveStreams.fromPublisher(itemList\u可观察)
this.liveItemList.addSource(liveItemList){itemList->
this.liveItemList.setValue(itemList)
this.liveItemList.removeSource(liveItemList)}
}
有趣的observeReposFromServer():LiveData{
返回liveGitResult
}
有趣的observeItemList():LiveData{
返回liveItemList
}
有趣的电话
{
liveGitResult.value=null
liveItemList.value=null
mainRepository.clearDisposables()
}
}
MainRepository:

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

}
class MainRepository@Inject构造函数(mainApi:mainApi){
私有val mainApi:mainApi
私有val一次性用品:CompositeDisposable=CompositeDisposable()
初始化{
this.mainApi=mainApi
}
fun fetchToDosFromServer(filter\u search:String):可观察{
lateinit var returnedData:可观察
//getAllRepo(filter_search)是一个翻新调用,它返回一个可流动的
returnedData=mainApi.getAllRepo(filter_search).subscribeOn(Schedulers.io())
.onErrorReturn(函数{throwable->
Log.e(Log_标签,“出错了”)
无效的
})
returnedData.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.订阅(对象:观察员){
覆盖订阅的乐趣(d:一次性){
一次性用品。添加(d)}
重写fun onComplete(){}
重写fun onNext(t:gitsresult){}
重写一个错误(e:Throwable){}
})
将返回的数据返回到可流动(背压调节缓冲区);
}
一次性用品{
如果(一次性使用!=空){
如果(!disposables.isDisposed)
一次性的
可处置的
}
}
}
现在,如果我在得到之前的结果之前运行应用程序并快速搜索多次,那么它的行为会很奇怪

  • 它在recyclerview中一个接一个地显示所有结果。以前的结果不应该被处理掉,也不会被转换为liveData吗
  • 它们也不是按顺序被调用的
  • 此外,不同时显示recyclerview数据和textView数据,可能使用来自不同Livedata源的观察者
那么,我哪里做错了


还有,如何在一条语句中编写
returnedData
的代码,而不是在我正在做的两条语句中编写(一条用于调用api,另一条用于重写subscribe方法).

对于类似的情况,我保留了一堆一次性订阅,并在开始新订阅时处理最旧的订阅。我在其中运行OkHtttp请求,因此在处理时,它们会被中断。

对于在用户创建另一个请求时取消以前的改装请求,而以前的请求仍在进行中,您可以使用kotlin的协同程序来实现夏娃

您可以使用suspend函数启动协同路由,该函数调用您的api请求,并在启动协同路由时保留返回的“Job”对象的引用。当您的用户在上一个请求进行时发送另一个搜索请求时,您只需使用“Job.isActive”检查上一个改装请求是否在pr中ogress与否,如果它处于活动状态,则可以调用“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的存储库