安卓关于Recycle布局的学习和使用 适配器
安卓关于Recycle布局的学习和使用 适配器
想要实现下面的效果

首先创建 recyclerView
在在 fragment_place.xml 布局文件中定义了 RecyclerView 组件

第二步:设置 LayoutManager
为 RecyclerView 设置了线性布局管理器,使列表项垂直排列显示。
binding.recyclerView.layoutManager = LinearLayoutManager(activity)
第三步:创建适配器
创建了一个 PlaceAdapter 实例,并将其设置为 RecyclerView 的适配器。PlaceAdapter{} 中的空大括号是传递给适配器的点击回调函数,当用户点击列表项时会触发。
adapter = PlaceAdapter {}
binding.recyclerView.adapter = adapter
第一步:定义适配器类
PlaceAdapter 继承自 ListAdapter,使用 DiffUtil 来优化列表更新
接收一个点击回调函数 onItemClick,当用户点击列表项时调用
指定数据类型为 place,ViewHolder 类型为内部类 viewHolder
使用自定义的 PlaceDiffCallback 来进行数据比较
class PlaceAdapter(private val onItemClick: (place) -> Unit): ListAdapter<place,PlaceAdapter.viewHolder>(PlaceDiffCallback())
第二步:创建 ViewHolder
通过 ViewBinding inflate 列表项布局 item_place.xml
创建并返回自定义的 viewHolder 实例
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): viewHolder {
val binding = ItemPlaceBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return viewHolder(binding)
}
第三步:绑定数据到 ViewHolder
获取指定位置的数据项
调用 ViewHolder 的 bind 方法绑定数据
override fun onBindViewHolder(
holder: viewHolder,
position: Int
) {
holder.bind(getItem(position))
}
第四步:实现ViewHolder内部类
ViewHolder内部类持有ItemPlaceBinding引用
bind方法负责将place数据绑定到UI组件:
place.name绑定到id为"place"的TextView
place.adm1和place.country组合后绑定到id为"tv_place_addres"的TextView
设置整个item的点击事件,触发传入的onItemClick回调
inner class viewHolder(private val binding: ItemPlaceBinding):ViewHolder(binding.root){
fun bind(place: place){
//绑定地名和详细地址名
binding.place.text = place.name
binding.tvPlaceAddres.text = "${place.adm1},${place.country}"
//设置点击事件
itemView.setOnClickListener {
onItemClick(place)
}
}
}
第五步:实现DiffUtil回调
PlaceDiffCallback用于比较列表中的新旧数据项
areItemsTheSame通过比较id判断是否为同一项
areContentsTheSame判断内容是否相同
class PlaceDiffCallback: DiffUtil.ItemCallback<place>() {
override fun areItemsTheSame(oldItem: place, newItem: place): Boolean {
//判断id是否相同
return oldItem.id == newItem.id
}
//判断内容是否相同
override fun areContentsTheSame(oldItem: place, newItem: place): Boolean {
return oldItem == newItem
}
}
使用适配器
提交数据列表
adapter.submitList(places)
if (places.isNotEmpty()==true){
//如果有数据,显示列表,隐藏空状态
binding.recyclerView.visibility = View.VISIBLE
binding.emptyStateLayout.visibility = View.GONE
adapter.submitList(places)
}else{
//如果没有数据,显示空状态,隐藏列表
binding.recyclerView.visibility = View.GONE
binding.emptyStateLayout.visibility = View.VISIBLE
result.exceptionOrNull()?.printStackTrace()
}
拓展 也可以把adapter替换为普通的RecyclerView.Adapter
/**
* @description: 创建adapter作为绑定$
* @author: $
* @date: $ $
*/
class PlaceAdapter(private val onItemClick: (place) -> Unit): RecyclerView.Adapter<PlaceAdapter.viewHolder>(){
private var places = listOf<place>()
fun setPlaces(newPlaces: List<place>) {
places = newPlaces
notifyDataSetChanged()
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): viewHolder {
val binding = ItemPlaceBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return viewHolder(binding)
}
override fun onBindViewHolder(
holder: viewHolder,
position: Int
) {
holder.bind(places[position])
}
override fun getItemCount(): Int = places.size
inner class viewHolder(private val binding: ItemPlaceBinding): RecyclerView.ViewHolder(binding.root){
fun bind(place: place){
//绑定地名和详细地址名
binding.place.text = place.name
binding.tvPlaceAddres.text = "${place.adm1},${place.country}"
//设置点击事件
itemView.setOnClickListener {
onItemClick(place)
}
}
}
}
同时需要修改PlaceFragment中使用adapter的地方:
if (places.isNotEmpty()==true){
//如果有数据,显示列表,隐藏空状态
binding.recyclerView.visibility = View.VISIBLE
binding.emptyStateLayout.visibility = View.GONE
adapter.setPlaces(places)
}else{
// ... existing code ...
//如果输出框为空,则晴空列表并显示空状态
binding.recyclerView.visibility = View.GONE
binding.emptyStateLayout.visibility = View.VISIBLE
adapter.setPlaces(emptyList())

浙公网安备 33010602011771号