总的来说,RecyclerView只是负责滚动显示的功能,Adapter才决定内容,MainActivity中使用 LayoutManagers来决定RecyclerView的布局样式(线性,网格,瀑布流,滚动方向)
用法
1.将 RecyclerView 添加到布局中
2.创建一个item.xml文件作为显示的子项
3.为 RecyclerView 实现 Adapter
1.为 Adapter 创建一个新类,例如 ItemAdapter。
class ItemAdapter(private val context: Context, private val dataset: List) {
}
2.创建用于代表单个列表项视图的自定义 ViewHolder 类(ItemViewHolder)。从 RecyclerView.ViewHolder 类进行扩展。
class ItemAdapter(private val context: Context, private val dataset: List) {
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
val textView: TextView = view.findViewById(R.id.item_title)
}
}
3.修改 ItemAdapter 类,以便从 RecyclerView.Adapter 类通过自定义 ViewHolder 类进行扩展。
class ItemAdapter(
private val context: Context,
private val dataset: List
) : RecyclerView.Adapter() {
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
val textView: TextView = view.findViewById(R.id.item_title)
}
}
4.在 Adapter 内实现以下方法:getItemsCount()、onCreateViewHolder() 和 onBindViewHolder()。
override fun getItemCount(): Int {
return dataset.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
// create a new view
val adapterLayout = LayoutInflater.from(parent.context)
.inflate(R.layout.list_item, parent, false)
return ItemViewHolder(adapterLayout)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
holder.textView.text = context.resources.getString(item.stringResourceId)
}
4.修改 MainActivity 以使用 RecyclerView(使用了ViewBinding)
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val myDataset = Datasource().loadAffirmations()
binding.recyclerView.adapter = ItemAdapter(this,myDataset)
binding.recyclerView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)
binding.recyclerView.setHasFixedSize(true)
//实现翻页效果
LinearSnapHelper().attachToRecyclerView(binding.recyclerView)
}
}
在ViewBinding中使用
class TypeAdapter: RecyclerView.Adapter() {
private val typeList = listOf("main course",
"side dish",
"dessert",
"appetizer",
"salad",
"bread",
"breakfast",
"soup",
"beverage",
"sauce",
"marinade",
"fingerfood",
"snack",
"drink")
class ItemViewHolder(binding: TypeItemBinding): RecyclerView.ViewHolder(binding.root){
val titleTextView: TextView = binding.titleText
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val adapterLayout = LayoutInflater.from(parent.context)
return ItemViewHolder(TypeItemBinding.inflate(adapterLayout))
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = typeList[position]
holder.titleTextView.text = item
}
override fun getItemCount(): Int {
return typeList.size
}
}
class RecipeFragment : Fragment() {
private lateinit var binding: FragmentRecipeBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentRecipeBinding.inflate(inflater)
//recyclerView
binding.typeRecyclerView.layoutManager = LinearLayoutManager(requireContext(),RecyclerView.HORIZONTAL,false)
binding.typeRecyclerView.adapter = TypeAdapter()
return binding.root
}
}
tips:
RecyclerView 微件可帮助您显示数据列表。
RecyclerView 使用 Adapter 模式来调整和显示数据。
ViewHolder 为 RecyclerView 创建并存储视图。
一个 ViewHolder 代表一个列表项视图
RecyclerView 附带内置 LayoutManagers。RecyclerView 将列表项的布局工作委托给 LayoutManagers。
RecyclerView的缓存机制
发现了一篇很好的文章:
https://www.jianshu.com/p/f9e21269da26
简单来说就是Recyclerview在获取ViewHolder时在Scrap(屏幕内的item)和Cache(屏幕外前后的几个item)通过Position寻找缓存,然后是ViewCacheExtension中自己定义的缓存,此时无需重新绑定数据;若没有找到则在RecycledViewPool中通过ViewType寻找缓存,找到后的数据是脏数据,需通过onBindViewHolder重新绑定数据。
通过onViewAttachedToWindow()方法获取item的关注次数
RecyclerView的性能优化
1.在onCreateViewHolder里设置点击按钮事件
达到一个view对应一个viewHolder对应一个onClickListener
2.使用LinearLayout.setInitialPrefetchItemCount()
当嵌套使用RecyclerView时(比如一个竖向的RecyclerView的itemView是一个横向的RecyclerView)使用LinearLayout.setInitialPrefetchItemCount()
(只有RecyclerView嵌套时并且LinearLayout能用这个api),进行预渲染横向列表初次显示时可见的item个数。
3.使用RecyclerView.setHasFixedSize()
4.多个RecyclerView共用一个RecycledViewPool
val recycledViewPool = RecyclerView.RecycledViewPool()
binding.recyclerView1.setRecycledViewPool(recycledViewPool)
binding.recyclerView2.setRecycledViewPool(recycledViewPool)
binding.recyclerView3.setRecycledViewPool(recycledViewPool)
5.DiffUtil
见博客:https://blog.csdn.net/zxt0601/article/details/52562770
ItemDecoration的用处
1.画分割线:DividerItemDecoration
2.高亮item
3.item分组