Android如何基于LinkedHashMap渲染RecyclerView并为每个Key绑定对应布局
实现方案
1. 预处理数据集,建立Key与ViewType的映射
RecyclerView基于线性位置索引渲染,你需要先将有序的LinkedHashMap<String, MutableList<CustomClass>>结构打平为一维列表,同时为每个Key分配唯一的ViewType,保证同一个Key下的所有数据对应同一种布局类型。
- 首先定义通用的列表项包装类:
data class RvWrapperItem( val viewType: Int, val data: CustomClass )
- 遍历LinkedHashMap生成最终的Adapter数据集:
// 存储Key到ViewType的映射,保证每个Key对应唯一布局类型 val keyViewTypeMap = linkedMapOf<String, Int>() yourLinkedHashMap.keys.forEachIndexed { index, key -> keyViewTypeMap[key] = index // 直接用索引作为ViewType,天然唯一不冲突 } // 打平哈希表为一维列表 val adapterData = mutableListOf<RvWrapperItem>() yourLinkedHashMap.forEach { (key, dataList) -> val currentViewType = keyViewTypeMap[key]!! dataList.forEach { customItem -> adapterData.add(RvWrapperItem(currentViewType, customItem)) } }
2. 重写Adapter的getItemViewType方法
直接返回当前位置对应的ViewType即可:
override fun getItemViewType(position: Int): Int { return adapterData[position].viewType }
3. 按ViewType创建和绑定ViewHolder
在onCreateViewHolder中根据ViewType加载对应布局、创建对应ViewHolder,在onBindViewHolder中按ViewHolder类型做差异化绑定逻辑:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(parent.context) return when(viewType) { // 第一个Key对应的布局和ViewHolder 0 -> Type1ViewHolder(inflater.inflate(R.layout.layout_key1, parent, false)) // 第二个Key对应的布局和ViewHolder 1 -> Type2ViewHolder(inflater.inflate(R.layout.layout_key2, parent, false)) // 其他Key对应的逻辑以此类推 else -> throw IllegalArgumentException("不支持的ViewType:$viewType") } } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { val currentItem = adapterData[position] when(holder) { is Type1ViewHolder -> holder.bind(currentItem.data) is Type2ViewHolder -> holder.bind(currentItem.data) // 其他ViewHolder的绑定逻辑以此类推 } }
可选扩展:支持分组标题
如果需要在每个Key对应的分组前展示标题,只需要给标题新增单独的ViewType,在打平数据集的时候先插入对应Key的标题项,再插入该Key下的所有数据项即可。
注意事项
- 基于LinkedHashMap的有序特性,打平后的列表顺序和Key的插入顺序完全一致,不会出现布局错乱
- 后续动态更新哈希表内容时,重新生成一次adapterData,调用
notifyDataSetChanged或者搭配DiffUtil做局部更新即可 - 新增Key类型时,只需要同步更新
keyViewTypeMap映射、onCreateViewHolder、onBindViewHolder三处逻辑即可,无需修改现有流程
内容的提问来源于stack exchange,提问作者Pinki
相关产品推荐
相关产品推荐

