Как перестать наблюдать за старыми статусами ответов RxJava без удаления?

у меня такой случай. Пользователь запускает цепочку запросов, нажимая кнопку. Затем он сделает загрузку двух фотографий. Однако после начала загрузки фотографий он может вернуться и начать процесс заново.

Мой 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() возвращает предыдущий результат

0
0
206
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Хорошо, если я правильно понял ваш случай, вы хотите отбросить ответ от первой загрузки и принять во внимание ответ от второй, или обобщить: игнорировать любые предыдущие ответы и принимать во внимание только последние.

Если это так, то одним из простых решений будет проверять 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, то вы просто отбрасываете этот ответ.

Вау, это то, что мне действительно нужно! Спасибо за понимание. Только один вопрос: например, если было загружено 50 процентов фотографий, вызов dispose не загрузит остальные? А может загрузится, но отклика не будет? Мне нужен второй чехол, он решит все мои проблемы. Как насчет композитного Disposable.clear()? Будет ли это прервать фактический процесс загрузки?

Viktor Vostrikov 22.06.2019 16:47

Да, я тоже думал о случайном хэше... кажется, по-другому нельзя. Я также думал о каком-то поведении flatMap, там я бы создал отдельные темы и удалил их вместо фактической загрузки.

Viktor Vostrikov 22.06.2019 18:13

Перешел на hashCode, работает хорошо. Будет ли hashCode нового объекта всегда возвращать другой hashCode? Даже если предыдущий объект был освобожден gc, он будет использовать новый или нет?

Viktor Vostrikov 22.06.2019 18:38

Другие вопросы по теме