You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多类型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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:15:13