所有ViewHolders同时创建

我有RecyclerView

<android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipe_task_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/toolbar"> <android.support.v4.widget.NestedScrollView android:id="@+id/scroll_task_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:focusableInTouchMode="true" android:orientation="vertical"> <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rv_task_list" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/background_task_list" /> <android.support.v4.widget.Space android:layout_width="match_parent" android:layout_height="80dp" /> </LinearLayout> </android.support.v4.widget.NestedScrollView> </android.support.v4.widget.SwipeRefreshLayout> 

初始化:

 rv_task_list.layoutManager = LinearLayoutManager(context) rv_task_list.layoutManager.setAutoMeasureEnabled(true) rv_task_list.isNestedScrollingEnabled = false rv_task_list.adapter = adapter 

在适配器中设置数据:

  data.addAll(tasksToAdapter) notifyDataSetChanged() 

(UPD)适配器:

 class TaskAdapter(private val view: ITaskList) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { val data: MutableList<ITaskItem> = mutableListOf() lateinit var context: Context override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { Log.e("TaskAdapter", "onCreateViewHolder") context = parent.context if (viewType == TITLE_TYPE) { val view = LayoutInflater.from(context).inflate(R.layout.card_title, parent, false); return TaskTitleViewHolder(view); } else { val view = LayoutInflater.from(context).inflate(R.layout.card_task, parent, false); return TaskViewHolder(view); } } override fun getItemViewType(position: Int): Int { return data[position].getTaskType() } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { Log.e("TaskAdapter", "onBindViewHolder(${position})") if (getItemViewType(position) == TITLE_TYPE) { (holder as TaskTitleViewHolder).bind(data[position] as TaskTitle) } else { val task = data[position] as Task (holder as TaskViewHolder).bind(task) holder.itemView.setOnClickListener { view.onSelectTask(task.id) } } } fun setData(tasks: List<Task>, showAllTasks: Boolean = false) { data.clear() val tasksToAdapter: MutableList<ITaskItem> = mutableListOf() // List creating data.addAll(tasksToAdapter) notifyDataSetChanged() } override fun getItemCount(): Int = data.size // ViewHolders class TaskViewHolder(view: View) : RecyclerView.ViewHolder(view) { private val tvTaskInfo: TextView = view.findViewById(R.id.tv_task_info) private val tvTaskComments: TextView = view.findViewById(R.id.tv_task_comments) private val tvTaskTitle: TextView = view.findViewById(R.id.tv_task_title) private val viewHeader: View = view.findViewById(R.id.view_header) private val tvEstimate: TextView = view.findViewById(R.id.tv_estimate) private val layoutExpectedDate: LinearLayout = view.findViewById(R.id.layout_expected_date) private val tvExpectedDate: TextView = view.findViewById(R.id.tv_expected_date) private val ivIconComments: ImageView = view.findViewById(R.id.iv_comments_icon) private val ivFlagComments: ImageView = view.findViewById(R.id.iv_flag_icon) private val ivIconClock: ImageView = view.findViewById(R.id.iv_clock_icon) private val layoutDateInformation: LinearLayout = view.findViewById(R.id.layout_date_information) fun bind(task: Task) { tvTaskInfo.text = "${task.projectName} ${task.id} (${task.type.localization})" if (task.commentsUnread == 0) { tvTaskComments.setTextColor(getColor(R.color.task_list_font_color_alpha)) ivIconComments.setImageDrawable(ContextCompat.getDrawable(App.get(), R.drawable.ic_with_readed_message)) } else { tvTaskComments.setTextColor(getColor(R.color.task_list_font_color)) ivIconComments.setImageDrawable(ContextCompat.getDrawable(App.get(), R.drawable.ic_with_unreaded_message)) } tvTaskComments.text = "${task.commentsUnread}/${task.commentsAll}" tvTaskTitle.text = Html.fromHtml(task.title) viewHeader.setBackgroundColor(getColorToTaskState(task.status)) layoutDateInformation.visibility = View.GONE if (!(task.status == TaskState.InWork || task.status == TaskState.Negotiation)) { return } if (task.getFormattedExpectedDate().isNotBlank()) { tvExpectedDate.text = task.getFormattedExpectedDate() layoutExpectedDate.visibility = View.VISIBLE } else { layoutExpectedDate.visibility = View.GONE } layoutDateInformation.visibility = View.VISIBLE ivIconClock.visibility = View.GONE if (task.type == TaskType.EstimateRework || task.type == TaskType.Design) { with (task.getFormattedEstimateTime()) { if (isNotBlank()) { tvEstimate.text = "${App.get().getString(R.string.estimated)} ${task.getFormattedEstimateTime()}" tvEstimate.visibility = View.VISIBLE } else tvEstimate.visibility = View.GONE } ivIconClock.visibility = View.VISIBLE ivIconClock.setImageDrawable(getImage(R.drawable.ic_clock)) ivIconClock.setColorFilter(getColor(R.color.task_list_clock_estimated), PorterDuff.Mode.SRC_ATOP) ivFlagComments.setImageDrawable(null) } else { tvEstimate.text = task.roughEstimate ?: "" ivIconClock.visibility = View.VISIBLE ivIconClock.setImageDrawable(getImage(R.drawable.ic_clock)) ivFlagComments.setImageDrawable(getImage(R.drawable.ic_flag)) } } } class TaskTitleViewHolder(view: View) : RecyclerView.ViewHolder(view) { private val tvTaskTitle: TextView = view.findViewById(R.id.tv_tasks_title) private val layoutCircle: FrameLayout = view.findViewById(R.id.layout_title_circle) private val layoutCircleAdditional: FrameLayout = view.findViewById(R.id.layout_title_circle_additional) fun bind(taskTitle: TaskTitle) { tvTaskTitle.text = taskTitle.content.toUpperCase() setCircle(layoutCircle, taskTitle.taskState) if (taskTitle.additionalTaskState != null) { layoutCircleAdditional.visibility = View.VISIBLE setCircle(layoutCircleAdditional, taskTitle.additionalTaskState!!) } } private fun setCircle(layout: FrameLayout, state: TaskState) { if (state == TaskState.WaitToWork) { layout.background = getImage(R.drawable.ic_waiting) } else { val drawable = ContextCompat.getDrawable(App.get(), R.drawable.task_header_circle) drawable.setColorFilter(getColorToTaskState(state), PorterDuff.Mode.SRC_ATOP) layout.background = drawable } } } 

我有两种类型的查看持有人。 当我在适配器中设置数据时,所有ViewHolders(超过90)都是同时创建的。 onCreateViewHolderonBindViewHolderonBindViewHolder调用90次。

为什么会发生?

我认为你的问题是在NestedScrollView内使用RecyclerViewNestedScrollView展开来保存所有内部子项目(在这种情况下, RecyclerView )您可以尝试使用app:layout_behavior="@string/appbar_scrolling_view_behavior"但作为官方文档

切勿将RecyclerViewListView添加到滚动视图。 这样做会导致较差的用户界面性能和较差的用户体验。

我有一个类似的问题。 我相信在我的情况下解决方案是一个自定义的LayoutManager,禁用supportsPredictiveItemAnimations 。 我的代码在Kotlin中,但应该很容易适应Java:

 class SplitGridLayoutManager(context : Context, rowCount : Int, val columnCount : Int) : GridLayoutManager(context, rowCount, GridLayoutManager.HORIZONTAL, false) { override fun supportsPredictiveItemAnimations() = false ... } 

由于您的RecyclerView上的android:layout_height="wrap_content"

你应该给它一个尺寸。 wrap_content将自行包装所有90个项目,尝试创建所有这些视图。 使用match_parent或其他设置高度。