Recycler Просмотр проблемы с переработкой

У меня есть recyclerView. Когда я делаю запрос для обновления, если новые данные представляют собой только один элемент списка, то представление ресайклера загружает этот элемент идеально. Но если обновленные данные содержат 2 или более, то я думаю, что представление не перерабатывается должным образом. В actionContainer должен быть добавлен только один элемент для каждого из обновленных элементов списка. Но во время извлечения для обновления, ТОЛЬКО КОГДА есть 2 или более элементов списка, которые нужно обновить, actionContainer показывает 2 данных, а должен быть только один. Может ли кто-нибудь помочь мне исправить это?

override fun onBindViewHolder(holder: HistoryListAdapter.ViewHolder?, position: Int) {
            info("onBindViewHolder =>"+listAssets.size)
            info("onBindViewHolder itemCount =>"+itemCount)
            info("onBindViewHolder position =>"+position)
        val notesButton = holder?.notesButton
        val notesView = holder?.notesTextView

        val dateTime = listAssets[position].date
        val location = listAssets[position].location

        val sessionId = listAssets[position].id
        holder?.sessionID = sessionId
        holder?.portraitImageView?.setImageDrawable(listAssets[position].image)
        holder?.titleTextView?.text = DateTimeFormatter.getFormattedDate(context, dateTime)

        val timeString = DateTimeFormatter.getFormattedTime(context, dateTime)

        if (location.length != 0) {
            holder?.subtitleTextView?.text = "$timeString @ $location"
        } else {
            holder?.subtitleTextView?.text = "$timeString"
        }

        val data = listAssets[position].data

        for (actionData in data) {
            val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            val parent = inflater.inflate(R.layout.history_card_action, null)

            val icon = parent?.findViewById(R.id.historyActionIcon) as ImageView
            val title = parent?.findViewById(R.id.historyActionTitle) as TextView
            val subtitle = parent?.findViewById(R.id.historyActionSubtitle) as TextView

            var iconDrawable: Drawable? = null

            when(actionData.type) {

                ActionType.HEART -> {
                    iconDrawable = ContextCompat.getDrawable(context, R.drawable.heart)
                }
                ActionType.LUNGS -> {
                    iconDrawable = ContextCompat.getDrawable(context, R.drawable.lungs)
                }
                ActionType.TEMPERATURE -> {
                    iconDrawable = ContextCompat.getDrawable(context, R.drawable.temperature)
                }
            }

            icon.setImageDrawable(iconDrawable)

            val titleString = actionData.title

            titleString?.let {
                title.text = titleString
            }

            val subtitleString = actionData.subtitle

            subtitleString?.let {
                subtitle.text = subtitleString
            }

            holder?.actionContainer?.addView(parent)
        }


        val notes = listAssets[position].notes
        notesView?.text = notes

        if (notes.length == 0) {
            notesButton?.layoutParams?.width = 0
        } else {
            notesButton?.layoutParams?.width = toggleButtonWidth
        }

        if (expandedNotes.contains(sessionId)) {
            notesView?.expandWithoutAnimation()
        } else {
            notesView?.collapseWithoutAnimation()
        }

        notesButton?.onClick {
            notesView?.toggleExpansion()
        }
    }


        data class ListAssets(val id: String,
                                  val date: Date,
                                  val location: String,
                                  val notes: String,
                                  val image: Drawable,
                                  val data: ArrayList<ListData>)

            data class ListData(val type: ActionType,
                                val title: String?,
                                val subtitle: String?)

    override fun onViewRecycled(holder: HistoryListAdapter.ViewHolder?) {
            super.onViewRecycled(holder)

            if (holder != null) {
    holder.actionContainer.removeAllViewsInLayout()
                holder.actionContainer.removeAllViews()

                val notesTextView = holder.notesTextView

                if (notesTextView != null) {
                    if (notesTextView.expandedState) {
                        val sessionID = holder.sessionID

                        sessionID?.let {
                            val sessionSearch = expandedNotes.firstOrNull {
                                it.contentEquals(sessionID)
                            }

                            if (sessionSearch == null) {
                                expandedNotes.add(sessionID)
                            }
                        }

                    } else {
                        val sessionID = holder.sessionID

                        sessionID?.let {
                            val sessionSearch = expandedNotes.firstOrNull {
                                it.contentEquals(sessionID)
                            }

                            if (sessionSearch != null) {
                                expandedNotes.remove(sessionSearch)
                            }
                        }
                    }
                }
            }

        }

person User    schedule 22.01.2016    source источник


Ответы (3)


Во-первых, вам, вероятно, не следует переопределять onViewRecycled(), если только вам не нужно выполнять какую-то очень специфическую очистку ресурсов. Место, где вы хотите настроить представления перед отображением, — onBindViewHolder().

Во-вторых, вам не нужно динамически добавлять или удалять представления в элементе RecyclerView, проще и эффективнее переключать видимость представления только между VISIBLE и GONE. В тех случаях, когда этого недостаточно, потому что представления слишком разные, вы должны объявить разные типы представлений, что создаст отдельные ViewHolder для каждого типа представления.

person BladeCoder    schedule 23.01.2016

Вы не должны удалять или добавлять какое-либо представление при переопределении метода onBindViewHoder() адаптера RecyclerView, потому что в следующий раз, когда используется переработанный макет, удаленные представления не будут найдены. Вместо этого вы можете использовать отображение/скрытие представления.

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

Точно так же, если вы удаляете какое-либо представление из макета динамически, позже, когда этот макет будет переработан, он не будет содержать представление, которое вы удалили ранее.

person Sachin Saxena    schedule 08.09.2016

Я реализовал RecyclerView и Retrofit, он имеет макет SwipeView (Pull to Refresh). Вот ссылка на репозиторий. https://github.com/frankodoom/Retrofit-RecyclerVew

person Frank Odoom    schedule 10.02.2017