у меня такой случай. Пользователь запускает цепочку запросов, нажимая кнопку. Затем он сделает загрузку двух фотографий. Однако после начала загрузки фотографий он может вернуться и начать процесс заново.
Мой CompositeDisposable() привязан к режиму просмотра.l будет очищен только после 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() возвращает предыдущий результат
Хорошо, если я правильно понял ваш случай, вы хотите отбросить ответ от первой загрузки и принять во внимание ответ от второй, или обобщить: игнорировать любые предыдущие ответы и принимать во внимание только последние.
Если это так, то одним из простых решений будет проверять compositeDisposable каждый раз перед началом новой загрузки. Если список не пуст, отбросьте все и добавьте в него новый одноразовый.
Что-то вроде этого:
fun uploadPhoto(){
if (compositeDisposable.size() > 0){
compositeDisposable.clear()
}
// ...
}
Обратите внимание на использование compositeDisposable.clear(), а не .dispose().
Относительно вашего дополнительного вопроса:
Таким образом, вызов compositeDisposable.clear() удалит каждый элемент в списке, в частности, это означает, что рабочий поток будет прерван, и да, в вашем случае это означает, что процесс загрузки будет прекращен.
Если вы хотите, чтобы загрузка продолжалась, вам придется придумать другой механизм, кроме очистки расходных материалов.
Я не уверен, что вы могли бы сделать это в Rx, но одна идея, не связанная с Rx, заключалась бы в том, чтобы иметь какой-то uploadId, например, сгенерированный случайный хэш, связанный с каждой загрузкой. Этот идентификатор должен быть передан вашему сетевому слою, а затем передан обратно в ответе.
Затем в ViewModel вы будете отслеживать currentUploadId и:
currentUploadId новым сгенерированным идентификаторомhandleResponse(...) получен, вы
проверьте response.uploadId с currentUploadId, если они не
match, то вы просто отбрасываете этот ответ.Да, я тоже думал о случайном хэше... кажется, по-другому нельзя. Я также думал о каком-то поведении flatMap, там я бы создал отдельные темы и удалил их вместо фактической загрузки.
Перешел на hashCode, работает хорошо. Будет ли hashCode нового объекта всегда возвращать другой hashCode? Даже если предыдущий объект был освобожден gc, он будет использовать новый или нет?
Вау, это то, что мне действительно нужно! Спасибо за понимание. Только один вопрос: например, если было загружено 50 процентов фотографий, вызов dispose не загрузит остальные? А может загрузится, но отклика не будет? Мне нужен второй чехол, он решит все мои проблемы. Как насчет композитного Disposable.clear()? Будет ли это прервать фактический процесс загрузки?