多类型Item的Adapter优化:ContactItem模型类更优实现方案咨询
优化多类型Item的联系人列表模型方案
问题背景
我开发了一个带分组标题的联系人列表,在Adapter中通过getItemViewType区分不同类型Item,核心实现如下:
@Override public int getItemViewType(int position) { ContactItem contactItem = mContacts.get(position); if (contactItem.getContactSeparator() == null) { if (contactItem.getContact().getContactType() == ContactType.SINGLE) { if (mShowSeparator) { return TYPE_CONTACT; } return TYPE_SEARCH_CONTACT; } if (mShowSeparator) { return TYPE_CONTACT_MULTIPLE; } return TYPE_SEARCH_CONTACT_MULTIPLE; } return TYPE_SEPARATOR; }
当前的ContactItem模型通过两个可空字段区分类型:
@Parcelize class ContactItem @JvmOverloads constructor( var contact: Contact? = null, var contactSeparator: String? = null ) : Parcelable
同时用ContactType枚举区分单/多号码联系人:
enum class ContactType { SINGLE, MULTIPLE }
if (numbers.size() > 1) { contact.setContactType(ContactType.MULTIPLE); }
现有方案存在逻辑嵌套深、模型字段冗余的问题,希望得到更简洁的多类型Item模型实现方案。
优化方案:采用密封类(Sealed Class)重构模型
Kotlin的密封类天然适配有限类型分支的场景,能让模型类型语义更明确,消除可空字段与冗余判断。
1. 定义密封类替代原ContactItem
@Parcelize sealed class ContactListItem : Parcelable { // 分组标题项 data class Separator(val title: String) : ContactListItem() // 联系人项,细分单/多号码类型 sealed class ContactItem : ContactListItem() { data class Single(val contact: Contact) : ContactItem() data class Multiple(val contact: Contact) : ContactItem() } }
- 分组标题由
Separator单独承载,无需通过可空字段区分 - 联系人项拆分为
Single和Multiple子类,替代原有ContactType枚举,类型语义更直观
2. 简化getItemViewType逻辑
密封类可通过is关键字直接判断类型,彻底消除多层嵌套:
@Override public int getItemViewType(int position) { ContactListItem item = mContacts.get(position); if (item instanceof ContactListItem.Separator) { return TYPE_SEPARATOR; } else if (item instanceof ContactListItem.ContactItem.Single) { return mShowSeparator ? TYPE_CONTACT : TYPE_SEARCH_CONTACT; } else if (item instanceof ContactListItem.ContactItem.Multiple) { return mShowSeparator ? TYPE_CONTACT_MULTIPLE : TYPE_SEARCH_CONTACT_MULTIPLE; } throw new IllegalArgumentException("未知Item类型"); }
若用Kotlin编写Adapter,逻辑会更简洁:
override fun getItemViewType(position: Int): Int { return when (val item = mContacts[position]) { is ContactListItem.Separator -> TYPE_SEPARATOR is ContactListItem.ContactItem.Single -> if (mShowSeparator) TYPE_CONTACT else TYPE_SEARCH_CONTACT is ContactListItem.ContactItem.Multiple -> if (mShowSeparator) TYPE_CONTACT_MULTIPLE else TYPE_SEARCH_CONTACT_MULTIPLE } }
3. 数据初始化时的类型构建
原有的ContactType判断可直接替换为对应密封类实例的创建:
// 替代原contact.setContactType逻辑 if (numbers.size() > 1) { mContacts.add(new ContactListItem.ContactItem.Multiple(contact)); } else { mContacts.add(new ContactListItem.ContactItem.Single(contact)); } // 添加分组标题 mContacts.add(new ContactListItem.Separator("A"));
优化后优势
- 类型安全:编译器会检查所有类型分支,避免遗漏判断
- 语义清晰:每个子类对应一种Item类型,无需通过可空字段推断类型
- 逻辑简化:消除多层嵌套判断,Adapter代码可读性大幅提升
- 冗余消除:移除
ContactType枚举及ContactItem中的可空字段,模型更简洁
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

