【发布时间】:2022-01-12 20:15:24
【问题描述】:
我正在制作一个看起来像图像的函数。
虽然图中没有显示,但这些项目可以通过按钮添加或删除。
项目由Header 和Detail 组成。该适配器还分别有HeaderAdapter和DetailAdapter。
我使用ConcatAdapter 来确保每个组有HeaderAdapter 和DetailAdatper,而不是整个列表。
因为我认为它比在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