【问题标题】:Is the RecyclerView absolutely wrong when there is only one item?当只有一项时,RecyclerView 是绝对错误的吗?
【发布时间】:2022-01-12 20:15:24
【问题描述】:

我正在制作一个看起来像图像的函数。

虽然图中没有显示,但这些项目可以通过按钮添加或删除。

项目由HeaderDetail 组成。该适配器还分别有HeaderAdapterDetailAdapter

我使用ConcatAdapter 来确保每个组有HeaderAdapterDetailAdatper,而不是整个列表。

因为我认为它比在one adapter 中使用multiview types 更易于管理(纯粹是我的观点)。

但我有一个问题。 HeaderAdapter.

从图片中可以看出,每个组有one header。因此,每个组的HeaderAdapter 中必须只有一个HeaderItem

在这种情况下,我认为没有太多理由使用适配器。

就我而言,将multiview type 用于one Adapter 会更好吗?

日常项目

sealed class RoutineItem(
    val layoutId: Int
) {
    data class Header(
        val id: String = "1",
        val workout: String = "2",
        val unit: String = "3",
    ) : RoutineItem(VIEW_TYPE) {
        companion object {
            const val VIEW_TYPE = R.layout.routine_item
        }
    }
    data class Detail(
        val id: String = UUID.randomUUID().toString(), // UUID
        val set: Int = 1,
        var weight: String ="",
        val reps: String = "1"
    ) : RoutineItem(VIEW_TYPE) {
        companion object {
            const val VIEW_TYPE = R.layout.item_routine_detail
        }
    }
}

HeaderAdapter

class HeaderAdapter(item: RoutineItem.Header) : BaseAdapter<RoutineItem.Header>(initialItem = listOf(item)) {

    override fun createViewHolder(itemView: View): GenericViewHolder<RoutineItem.Header> {
        return HeaderViewHolder(itemView)
    }

    override fun getItemCount(): Int = 1

    class HeaderViewHolder(itemView: View) : GenericViewHolder<RoutineItem.Header>(itemView)
}

DetailAdapter

class DetailAdapter(private val items: List<RoutineItem.Detail> = emptyList())
    : BaseAdapter<RoutineItem.Detail>(initialItem = items) {

    override fun createViewHolder(itemView: View): GenericViewHolder<RoutineItem.Detail> {
        return DetailViewHolder(itemView)
    }

    override fun getItemCount(): Int = items.size

    class DetailViewHolder(itemView: View) : GenericViewHolder<RoutineItem.Detail>(itemView)
}

活动

class MainActivity : AppCompatActivity() {
    var concatAdpater: ConcatAdapter = ConcatAdapter()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val rv: RecyclerView = findViewById(R.id.rv)

        val adapterItems: ArrayList<Pair<RoutineItem.Header, List<RoutineItem.Detail>>> = arrayListOf()
        val childItems : List<RoutineItem.Detail> = listOf(
            RoutineItem.Detail(),
            RoutineItem.Detail(),
            RoutineItem.Detail(),
            RoutineItem.Detail(),
            RoutineItem.Detail()
        )

        adapterItems.add(Pair(RoutineItem.Header(), childItems))
        adapterItems.add(Pair(RoutineItem.Header(), childItems))
        adapterItems.add(Pair(RoutineItem.Header(), childItems))
        for ((header, list) in adapterItems) { // 1 adapter per group
            concatAdpater.addAdapter(HeaderAdapter(header))
            concatAdpater.addAdapter(DetailAdapter(list))
        }
        rv.adapter = concatAdpater
    }
}

因为是测试代码,所以有部分功能没有实现! (例如,动态添加和删除项目..)

【问题讨论】:

  • 我认为为了简单性能,使用具有多个视图高度的单个适配器会更有意义。如果 RecyclerView 由多个适配器组成,每个适配器包含的视图比屏幕上的视图少,那么它就不能做太多的回收。 RecyclerView 的目的是回收从屏幕一端滚动的视图,并将它们重用于滚动到另一端屏幕上的视图。但是不能在 ConcatAdapter 中的适配器之间共享视图,因此几乎所有 RecyclerView 的性能优势都被浪费了。
  • @Tenfour04 那么在我的情况下,每个组的HeaderAdater中只有一个HeaderItem,所以每个组的HeaderAdapter中没有足够的Header可以滚动,所以RecyclerView根本无法在HeaderAdapter中回收?
  • 正确。每个 HeaderItem 的 ViewHolder 都是唯一的实例。此外,在您的示例图片中,您的 Detail 项组都没有大到足以覆盖屏幕,因此 DetailItem 的 ViewHolder 也不会被回收。即使它们足以覆盖屏幕,一旦它到达下一组,下一个适配器也必须为其自己的 DetailItems 膨胀新的视图持有者。
  • 每个适配器实例都有自己的 ViewHolders 池。他们不互相分享,所以不,没有回收利用。您没有将 ConcatAdapter 用于其预期目的。它用于将完全不相关的项目的单独列表组合到单个滚动视图中。想想一个商店应用程序,它在顶部向您显示一些特别优惠,然后在同一列表中的下方显示搜索结果列表。 ConcatAdapter 可以让您将这些完全不同的东西放在单独的适配器中,以进行代码组织。
  • 哦;我没有意识到有一个选择。我没有深入研究它,但这可能会解决它并允许共享相同的 ViewHolder 类(如果它们是同一个类)。

标签: android kotlin android-recyclerview android-concatadapter


【解决方案1】:

使用单个适配器总是更好,因为使用DiffUtil 更易于管理项目动画和状态更改。此外,它更易于维护且更高效(在速度和资源管理方面)。

更详细的答案:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    • 1970-01-01
    相关资源
    最近更新 更多