如何将分组后的Map解构为RecyclerView所需的列表?
实现按国家分组的机场列表(适配RecyclerView)
核心思路
把分组后的Map<Country, List<Airport>>转换成单一扁平的混合列表,用多类型Adapter区分国家标题项和机场内容项,适配RecyclerView的展示需求。
步骤1:定义列表项类型
创建密封类区分两种列表项,让RecyclerView能识别不同类型的布局:
sealed class ListItem { data class CountryItem(val country: Country) : ListItem() data class AirportItem(val airport: Airport) : ListItem() }
步骤2:转换分组数据为扁平列表
遍历分组后的Map,依次添加国家项和对应的机场项(可按需排序):
// 假设已通过groupBy得到分组结果:val groupedAirports: Map<Country, List<Airport>> val flatListItemList = mutableListOf<ListItem>() // 按国家名称排序,让列表更规整 groupedAirports.toSortedMap(compareBy { it.name }).forEach { (country, airports) -> flatListItemList.add(ListItem.CountryItem(country)) // 按机场名称排序,优化展示顺序 airports.sortedBy { it.name }.forEach { airport -> flatListItemList.add(ListItem.AirportItem(airport)) } }
步骤3:实现多类型RecyclerView Adapter
重写getItemViewType区分布局类型,创建对应的ViewHolder绑定数据:
class AirportListAdapter(private val items: List<ListItem>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { companion object { private const val VIEW_TYPE_COUNTRY = 0 private const val VIEW_TYPE_AIRPORT = 1 } override fun getItemViewType(position: Int): Int { return when (items[position]) { is ListItem.CountryItem -> VIEW_TYPE_COUNTRY is ListItem.AirportItem -> VIEW_TYPE_AIRPORT } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(parent.context) return when (viewType) { VIEW_TYPE_COUNTRY -> { val view = inflater.inflate(R.layout.item_country, parent, false) CountryViewHolder(view) } else -> { val view = inflater.inflate(R.layout.item_airport, parent, false) AirportViewHolder(view) } } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (val item = items[position]) { is ListItem.CountryItem -> (holder as CountryViewHolder).bind(item.country) is ListItem.AirportItem -> (holder as AirportViewHolder).bind(item.airport) } } override fun getItemCount() = items.size // 国家项ViewHolder class CountryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(country: Country) { itemView.findViewById<TextView>(R.id.tv_country).text = country.name // 可添加样式调整,比如加粗背景色 } } // 机场项ViewHolder class AirportViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind(airport: Airport) { itemView.findViewById<TextView>(R.id.tv_airport_name).text = airport.name itemView.findViewById<TextView>(R.id.tv_airport_code).text = airport.code itemView.findViewById<TextView>(R.id.tv_city).text = airport.city.name } } }
步骤4:创建对应布局文件
- item_country.xml:用于展示国家标题,可设置加粗字体、灰色背景等区分样式
- item_airport.xml:展示机场名称、代码、城市等详细信息,布局风格与标题项区分开
注意事项
- 确保
Country类正确实现equals()和hashCode()(如果是数据类则默认实现),否则groupBy无法正确分组 - 可根据业务需求调整国家和机场的排序规则(比如按拼音、热门程度)
- 数据量大时,建议使用
DiffUtil优化RecyclerView的更新性能,避免卡顿
内容的提问来源于stack exchange,提问作者Arknes
相关产品推荐
相关产品推荐

