You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView onCreateViewHolder多次调用致应用卡顿问题求助

RecyclerView嵌套NestedScrollView时频繁触发onCreateViewHolder导致卡顿

我的RecyclerView嵌套在NestedScrollView内的复杂ViewGroup中,整体属于BottomSheet,层级结构为CoordinatorLayout -> FrameLayout -> NestedScrollView -> LinearLayout,RecyclerView上下还有其他视图。填充RecyclerView时,每个可见视图都会触发onCreateViewHolder;快速滚动时该方法也会频繁调用,导致应用卡顿。相关代码与布局如下:

适配器相关代码

private val adapter = Adapter()
enum class ViewItemType(val type: Int) {
    DEPARTURE_ITEM(1)
}

abstract class AdapterItem(val type: ViewItemType)
class DepartureItem(
    val d: Departure,
) : AdapterItem(ViewItemType.DEPARTURE_ITEM)

private open inner class ItemViewHolder(root: ViewGroup): RecyclerView.ViewHolder(root)
private inner class DepartureViewHolder(val root: ViewGroup): ItemViewHolder(root){
    val tripIcon = root.findViewById<ImageView>(R.id.trip_icon)
    val tripNumber = root.findText(R.id.trip_number)
    val tripDirection = root.findText(R.id.trip_direction)
    val tripDeparture = root.findText(R.id.trip_departure)

    fun bind(item: DepartureItem, onClick: ()->Unit) {
        root.setGone()
        with(item.d) {
            root.onClick {
                onClick.invoke()
            }

            tripNumber.text = busNumber
            tripDirection.text = direction
        }
        root.setVisible()
    }
}

private inner class Adapter : RecyclerView.Adapter<ItemViewHolder>(){
    var items = emptyList<DepartureItem>()

    override fun getItemCount() = items.size

    override fun getItemViewType(position: Int): Int {
        return items[position].type.type
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        App.log("DepartureList: onCreateViewHolder: creating item")
        return when(viewType){
            ViewItemType.DEPARTURE_ITEM.type -> {
                DepartureViewHolder((
                        CustomResources.inflateLayout(
                            a.layoutInflater,
                            R.layout.departure_board_item,
                            parent, false) as ViewGroup
                        ))
            }
            else -> {
                DepartureViewHolder((
                        CustomResources.inflateLayout(
                            a.layoutInflater,
                            R.layout.departure_board_item,
                            parent, false) as ViewGroup
                        ))
            }
        }
    }

    override fun onBindViewHolder(vh: ItemViewHolder, position: Int) {
        val r = items[position]
        when(r.type){
            ViewItemType.DEPARTURE_ITEM -> {
                (vh as? DepartureViewHolder)?.bind(
                    r as DepartureItem,
                    onClick = {
                        onDepartureClicked.invoke(r.d)
                    }
                )
            }
        }
    }
}


private fun refreshContent(board: List<Departure>, firstLoading: Boolean = false){
    if (firstLoading) progress.setProgress(true)
    cal.timeInMillis = System.currentTimeMillis()
    currMinutes = cal.get(Calendar.HOUR_OF_DAY)*60+cal.get(Calendar.MINUTE)
    currSeconds = cal.get(Calendar.HOUR_OF_DAY)*3600+cal.get(Calendar.MINUTE)*60+cal.get(Calendar.SECOND)

    val filtered = board.filter{computeMinutesToNow(currMinutes, it)>=0}
    val sl = filtered.sortedBy { it.realtimeDepartureInMins }
    fillerView.setVisibleNotGone(sl.isEmpty())
    adapter.items = sl.map { DepartureItem(it) }
    adapter.notifyDataSetChanged()
    if (firstLoading) progress.setProgress(false)
}

RecyclerView 初始化代码

list = findViewById<RecyclerView>(R.id.list).also { rv ->
                rv.isNestedScrollingEnabled = false
                rv.adapter = adapter
                rv.layoutManager = LinearLayoutManager(a)
            }

布局代码

<RelativeLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:clipChildren="false">

        <View
            android:id="@+id/fillerView"
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:visibility="gone"/>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/list"
            android:paddingTop="8dp"
            android:paddingBottom="8dp"
            android:clipToPadding="false"
            android:clipChildren="false"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <components.LoadingIndicator
            android:id="@+id/progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true" />

    </RelativeLayout>

内容的提问来源于stack exchange,提问作者Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 19:54:56