Как избежать IllegalStateException При вызове notifyDataSetChanged? - PullRequest
0 голосов
/ 08 июня 2018

У меня есть горизонтальный вид переработчика, называемый imageRecyclerView, где каждый столбец состоит только из одного ImageView.Класс адаптера для представления переработчика называется ImageAdapter.Набор данных адаптера imageRecyclerView представляет собой ArrayList строк, содержащих URL-адреса.ArrayList называется currentImageURLs.

Примечание. Целью всего этого кода является загрузка изображений в imageRecyclerView по одному за раз.

В методе onBindViewHolderмой ImageAdapter класс У меня есть следующий код.Этот код загружает изображение из набора данных адаптера в ImageView.Код также ждет, пока изображение не будет загружено в ImageView, прежде чем вызвать recursivelyLoadURLs, чтобы добавить новый элемент в набор данных адаптера.

    Glide.with(context)
            //items[[position] is a string that contains a URL 
            .load(items[position])
            .listener(object : RequestListener<Drawable> {
                override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                    holder.progressBar.visibility = View.GONE
                    context.recursivelyLoadURLs()
                    return false
                }

                override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    holder.progressBar.visibility = View.GONE
                    context.recursivelyLoadURLs()
                    return false
                }

            })
            .apply(RequestOptions()
                    .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC))
            .into(holder.imageView)

Метод recursivelyLoadURLs находится в родительском классе Activity.По сути, этот метод

1] добавляет еще один URL к набору данных адаптера imageRecyclerView и

2] вызывает notifyDataSetChanged, поэтому imageRecyclerView updates:

fun recursivelyLoadURLs() {


    if (currentImageURLs.size >= targetImageURLs.size) {
        return
    }

    currentImageURLs.add(targetImageURLs[currentImageURLs.size])

    //The code crashes on this line
    mainview.imageRecyclerView.adapter.notifyDataSetChanged()


}

Однако происходит сбой кода, за исключением java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling в строке, помеченной в приведенном выше примере кода.

Я подозреваю, что это происходит, потому что imageRecyclerView все еще вычисляет макет, когда notifyDataSetChanged вызывается.

Как я могу отложить вызов context.recursivelyLoadURLs, пока не закончится вычисление макета?

Или, как я могу добавить задержку внутри recursivelyLoadURLs, чтобы notifyDataSetChanged вызывается только после того, как imageRecyclerView завершит вычисление своего нового макета?

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

tompee предложил опубликовать Runnable, чтобы гарантировать, что представление переработчика выложило своих дочерних элементов перед запуском notifyDataSetChanged.

Таким образом, я заменил notifyDataSetChanged на

    mainview.imageRecyclerView.post({
        mainview.imageRecyclerView.adapter.notifyDataSetChanged()
    })

и это решило проблему.

0 голосов
/ 08 июня 2018

Вы можете прочитать документацию по RecyclerView.Adapter.notifyDataSetChanged

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

Если вы пишете адаптер, всегда будет более эффективно использовать более конкретные события изменения, если это возможно.Положитесь на notifyDataSetChanged () в качестве крайней меры.

Вот несколько советов, которые могут помочь * надеюсь, что это поможет:)

  1. Старайтесь не использовать notifyDataSetChanged(), особеннов вашем onBindViewHolder.Используйте notifyItemChanged(position) вместо этого.Это гораздо более эффективно и стоит меньше памяти.
  2. Если вам действительно нужно использовать notifyDataSetChanged(), используйте его ПОСЛЕ ТОГО, КАК вы готовы со ВСЕМИ вашими данными (возможно, получите его, когда currentImageURLs.size >= targetImageURLs.size)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...