如何在不处理的情况下停止观察旧的 RxJava 响应状态?
How to stop observing old RxJava response statuses without dispose?
我有这样的案例。用户通过单击按钮启动请求链。然后他会制作两张照片上传。然而,在开始上传照片后,他可能 return 并重新开始处理。
我的 CompositeDisposable() 附加到 viewModel 它只会在 onCleared() 之后被清除。这就是为什么会出现奇怪的问题:用户可能会开始上传照片,返回,重新开始 并且将传送来自旧请求 的响应,在上传新的之前!
我应该如何修改我所有的常规 RxJava 请求和 zip 运算符以仅处理新请求而不是旧请求。
同样,我不能在每个按钮事件之前调用 CompositeDisposable.dispose(),因为那样会终止上传过程。
我只需要处理可能的旧响应。
这是我的示例:
//called two times, for uploading
fun uploadPhoto(){
compositeDisposable.add(
apiService.networkRequest(linkedHashMap, url)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object: DisposableSingleObserver<retrofit2.Response<String>>() {
override fun onSuccess(t: retrofit2.Response<String>) {
// will provide result even if two new uploadPhoto() methods gets called
handleResponse(t)
}
override fun onError(e: Throwable) {
}
}))
}
}
fun handleResponse(response: retrofit2.Response<String>)
{
responseList.add(response) //saves number of responses
if(responseList.size == 2)
{
//calls new network request and creates a new logic.
}
}
问题是 handleResponse() 在 uploadPhoto() return 之前的结果
之后被调用
好的,如果我对你的情况理解正确的话,你想放弃第一次上传的响应并考虑第二次上传的响应,或者概括地说:忽略任何以前的响应并只考虑最新的响应。
如果是这样,那么一个简单的解决方案就是每次在开始新的上传之前检查 compositeDisposable
。如果列表不为空,则丢弃所有内容并向其中添加新的一次性用品。
像这样:
fun uploadPhoto(){
if(compositeDisposable.size() > 0){
compositeDisposable.clear()
}
// ...
}
注意使用 compositeDisposable.clear()
而不是 .dispose()
。
关于您的跟进问题:
因此,调用 compositeDisposable.clear()
将处理列表中的每一项,更具体地说,这意味着工作线程将被中断,是的,在您的情况下,这意味着上传过程将终止。
如果你想继续上传,那么除了清除一次性物品外,你还得想出一个不同的机制。
我不确定你是否可以在 Rx 中做到这一点,但不涉及 Rx 的一个想法是让某种 uploadId
,如生成的随机哈希,与每次上传相关联。此 ID 应提供给您的网络层,然后在响应中传回。
然后在 ViewModel
中,您将跟踪 currentUploadId
,并且:
- 每当用户执行新的上传时,使用新生成的 ID
更新 currentUploadId
- 每当收到
handleResponse(...)
时,您
检查 response.uploadId
和 currentUploadId
,如果他们不这样做
匹配,那么您只需丢弃此响应。
我有这样的案例。用户通过单击按钮启动请求链。然后他会制作两张照片上传。然而,在开始上传照片后,他可能 return 并重新开始处理。
我的 CompositeDisposable() 附加到 viewModel 它只会在 onCleared() 之后被清除。这就是为什么会出现奇怪的问题:用户可能会开始上传照片,返回,重新开始 并且将传送来自旧请求 的响应,在上传新的之前!
我应该如何修改我所有的常规 RxJava 请求和 zip 运算符以仅处理新请求而不是旧请求。
同样,我不能在每个按钮事件之前调用 CompositeDisposable.dispose(),因为那样会终止上传过程。
我只需要处理可能的旧响应。
这是我的示例:
//called two times, for uploading
fun uploadPhoto(){
compositeDisposable.add(
apiService.networkRequest(linkedHashMap, url)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(object: DisposableSingleObserver<retrofit2.Response<String>>() {
override fun onSuccess(t: retrofit2.Response<String>) {
// will provide result even if two new uploadPhoto() methods gets called
handleResponse(t)
}
override fun onError(e: Throwable) {
}
}))
}
}
fun handleResponse(response: retrofit2.Response<String>)
{
responseList.add(response) //saves number of responses
if(responseList.size == 2)
{
//calls new network request and creates a new logic.
}
}
问题是 handleResponse() 在 uploadPhoto() return 之前的结果
之后被调用好的,如果我对你的情况理解正确的话,你想放弃第一次上传的响应并考虑第二次上传的响应,或者概括地说:忽略任何以前的响应并只考虑最新的响应。
如果是这样,那么一个简单的解决方案就是每次在开始新的上传之前检查 compositeDisposable
。如果列表不为空,则丢弃所有内容并向其中添加新的一次性用品。
像这样:
fun uploadPhoto(){
if(compositeDisposable.size() > 0){
compositeDisposable.clear()
}
// ...
}
注意使用 compositeDisposable.clear()
而不是 .dispose()
。
关于您的跟进问题:
因此,调用 compositeDisposable.clear()
将处理列表中的每一项,更具体地说,这意味着工作线程将被中断,是的,在您的情况下,这意味着上传过程将终止。
如果你想继续上传,那么除了清除一次性物品外,你还得想出一个不同的机制。
我不确定你是否可以在 Rx 中做到这一点,但不涉及 Rx 的一个想法是让某种 uploadId
,如生成的随机哈希,与每次上传相关联。此 ID 应提供给您的网络层,然后在响应中传回。
然后在 ViewModel
中,您将跟踪 currentUploadId
,并且:
- 每当用户执行新的上传时,使用新生成的 ID 更新
- 每当收到
handleResponse(...)
时,您 检查response.uploadId
和currentUploadId
,如果他们不这样做 匹配,那么您只需丢弃此响应。
currentUploadId