Recycler View回收问题

时间:2016-01-22 06:34:06

标签: android-recyclerview recyclerview-layout

我有一个recyclerView。当我进行刷新刷新时,如果新数据只是一个列表项,则回收器视图可以完美地加载项。但是,如果更新的数据包含2个或更多,那么我认为视图不能正确回收。在actionContainer中,每个更新的列表项只应添加一个项目。但是在pull to refresh期间,只有当有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)
                            }
                        }
                    }
                }
            }

        }

3 个答案:

答案 0 :(得分:0)

首先,您可能不应该覆盖onViewRecycled(),除非您必须执行一些非常特殊的资源清理。 您希望在显示之前设置视图的位置是onBindViewHolder()

其次,您不需要在RecyclerView项目中动态添加或删除视图,仅在VISIBLE和{{1}之间切换视图的可见性更简单,更高效}}。如果由于视图太不相同而导致这种情况不够,则应声明不同的视图类型,这将为每种视图类型创建单独的GONE

答案 1 :(得分:0)

在覆盖RecyclerView Adapter的onBindViewHoder()方法时,不应删除或添加任何视图,因为下次使用回收的布局时,将无法找到已删除的视图。而不是这个,你可以在视图上使用show / hide。

如果您动态地向布局添加任何视图,稍后在回收此布局时,它还会包含您之前添加的额外视图。

同样,如果从布局中动态删除任何视图,稍后在回收此布局时,它不包含您之前删除的视图。

答案 2 :(得分:0)

我已经实施了RecyclerView和Retrofit,它具有SwipeView布局(Pull to Refresh)。这里是对repisitory的链接。 https://github.com/frankodoom/Retrofit-RecyclerVew

相关问题