У меня есть Recycler of Recyclers, который отображает постеры фильмов, очень похожие на Netflix или большинство галеристов приложений.
Всякий раз, когда я прокручиваю внутренние столбцы корзины, я извлекаю изображение из URL с помощью Picasso.
Это прекрасно работает, но всякий раз, когда изображение загружается в его представление изображения, позиция внешнего рециклера устанавливается в 0 и возвращается к первому ряду изображений.
Это мой внешний и внутренний переработчик:
внешний:
class OuterPreviewRowAdapter(private var homeFeedResponse: MutableList<RelatedItemsResponse> = mutableListOf(),
private val onItemClick: ((Int) -> Unit)?)
: RecyclerView.Adapter<OuterPreviewRowAdapter.ItemPreviewRowHolder>() {
inner class ItemPreviewRowHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val recyclerView: RecyclerView = itemView.innerPreviewRecycler
val categoryTitleTextView: TextView = itemView.innerListHeader
}
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): ItemPreviewRowHolder {
val itemRow = LayoutInflater.from(parent.context)
.inflate(R.layout.component_item_preview_row, parent, false)
return ItemPreviewRowHolder(itemRow)
}
override fun onBindViewHolder(holder: ItemPreviewRowHolder, position: Int) {
val categoryModel = homeFeedResponse[position]
val mediaItems = categoryModel.itemMediaPreviews?.filterNotNull() ?: listOf()
holder.categoryTitleTextView.text = categoryModel.categoryName
holder.recyclerView.apply {
val innerLayoutManager = LinearLayoutManager(holder.itemView.context, LinearLayoutManager.HORIZONTAL, false)
layoutManager = innerLayoutManager
adapter = InnerPreviewItemAdapter(mediaItems, onItemClick)
}
}
override fun getItemCount(): Int {
return homeFeedResponse.size
}
fun updateDataSetAndNotify(newFeed: List<RelatedItemsResponse>) {
homeFeedResponse.addAll(newFeed)
}
}
внутренний:
class InnerPreviewItemAdapter(private var mediaPreviewItems: List<ItemMediaPreviewsItem>,
private val onItemClick: ((ItemId: Int) -> Unit)?)
: RecyclerView.Adapter<InnerPreviewItemAdapter.ItemPreviewHolder>() {
inner class ItemPreviewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var itemTitle: TextView = itemView.itemTitle
var itemDuration: TextView = itemView.itemDuration
var itemPreviewImage: ImageView = itemView.itemPreviewImage
var progressSpinnerItemPreview: View = itemView.progressSpinnerItemPreview
}
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): ItemPreviewHolder {
val previewItemView = LayoutInflater.from(parent.context)
.inflate(R.layout.component_item_preview_item, parent, false)
return ItemPreviewHolder(previewItemView)
}
override fun onBindViewHolder(holder: ItemPreviewHolder, position: Int) {
val mediaItem = mediaPreviewItems[position]
holder.apply {
mediaItem.id?.let { itemId -> itemView.setOnClickListener { onItemClick?.invoke(itemId) } }
progressSpinnerItemPreview.visibility = View.VISIBLE
itemTitle.text = mediaItem.title
itemDuration.text = itemDuration.context.getString(R.string.MINUTES_WITH_ARGUMENT, mediaItem.length)
}
// TODO: (broel) disabling picasso solves the gallery recycler bug.
Picasso.get().load(mediaItem.contentPoster)
.fit()
.centerInside()
.error(R.drawable.ic_missing_content)
.into(holder.itemPreviewImage)
}
override fun getItemCount(): Int {
return mediaPreviewItems.size
}
}
И я создаю свой внешний переработчик в своем фрагменте так:
...
private fun setupMediaGalleryRecycler() {
val linearLayoutManager = LinearLayoutManager(context)
outerRecyclerAdapter = OuterPreviewRowAdapter(onItemClicked)
outerPreviewRecycler.adapter = outerRecyclerAdapter
outerPreviewRecycler.itemAnimator = DefaultItemAnimator()
outerPreviewRecycler.layoutManager = linearLayoutManager
}
...
Я пытался решить эту проблему уже неделю, но не приблизился к ее решению тогда, когда начал.
Я перепробовал все, что могу найти в сети, но пока безуспешно.
Вот что я пробовал:
- Настройка
setHasStableIds(true)
и переопределение getItemId(position:
Int)
- Переопределить
getItemViewType(position: Int)
для возврата в положение
- Передача общего пула просмотра внутреннему переработчику
setRecycledViewPool(viewPool)
- Попытка множества вариантов параметров Picasso (заполнителей, обработки изображений, обратных вызовов и т. Д.), Чтобы попытаться что-то исключить.
- Передать
Presenter
, держа данные вместо того, чтобы передавать сами данные.
Я также должен добавить, что я делаю только одну начальную выборку данных, поэтому notifyDataSetChanged вызываются только в первый (и единственный) раз, когда фрагмент настроен.
Я рад предоставить больше информации, если это необходимо.
Я просто хочу закрыть эту главу и продолжить работу над проектом.