Обновите адаптер просмотра ресайклера на наблюдаемую эмиссию - PullRequest
0 голосов
/ 07 мая 2020

При работе над чат-приложением возникла необходимость обработки изображений - их загрузки и выгрузки. Сама обработка выполняется с помощью Observables RxJava2; в то время как команды для загрузки или выгрузки выполняются из OnBindViewHolder () адаптера RecyclerView.

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    if (currentlyUsedPositionToMessageMap.containsKey(position)) {
        val message = currentlyUsedPositionToMessageMap[position]
        when (message) {
            is TextMessage -> (holder as TextMessageViewHolder).bind(message)
            is ImageMessage -> (holder as ImageMessageViewHolder).bind(message)
        }
    } else {
        val (messageType, downloadableMessage) = downloadableMessages[position]

        disposables += downloadableMessage                    //Observable
            .subscribeBy(
                onNext = {
                    currentlyUsedPositionToMessageMap[position] = it
                    notifyItemChanged(position)
                },
                onError = {
                    Log.e(LOG_TAG, Log.getStackTraceString(it))
                }
            )

        when (messageType){
            "image" -> (holder as ImageMessageViewHolder).showDefaultAnimation()
            "text" -> (holder as TextMessageViewHolder).showDefaultAnimation()
        }
    }
}

Идея для кода выше: если изображение (или текст) уже загружено, заполните ViewHolder с данными еще устанавливает задачу загрузки и заставляет ViewHolder показывать некоторую анимацию по умолчанию.

Возникла проблема: нет возможности обновить видимые ViewHolders после того, как загруженная задача была выполнена, потому что notifyItemChanged (position) вызывает следующую ошибку :

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView

Итак, как я могу разрешить это исключение? Другими словами, как я могу обновить ViewHolder в [положение] (если он виден) после успешной загрузки изображения с загруженным изображением?

1 Ответ

0 голосов
/ 07 мая 2020

Что случилось? Вкратце:

Обновление было выполнено на не полностью загруженном RecyclerView, что привело к исключению:

Невозможно вызвать этот метод, пока RecyclerView вычисляет макет или прокручивает

Примечание: « этот метод » относится к notifyItemChanged (позиция) для обновления элемента


Разработка:

Проблема была связана не с передачей Imaage, а с Обработка текста. Дизайн приложения заключался в том, что если текущий элемент является загружаемым изображением, тогда go для его загрузки; если это уже кэшированный текст, верните новый Observable с текстом из Android Main Thread. Итак, создание в основном потоке Observable ускорилось с заполнением данных RecyclerView ViewHolder. Таким образом, когда был возвращен Observable, RecyclerView не был загружен со всеми элементами, которые он должен был загрузить в другое время, что привело к выполнению операции обновления на незавершенном RecyclerView. Значит, исключение!

...