通用Adapter的尝试《第二篇》

本文介绍了如何使用MultiItemCommonAdapter实现ListView中不同类型的布局显示,通过MultiItemTypeSupport接口区分不同类型的Item并对应不同的布局。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

经过昨天一天的尝试与上午的一些努力,通用的adapter终于是可以用了。没有继承RecycleView,直接写就可以

上午主要对上一篇文章中没有进行介绍的MultiItemCommonAdapter和MultiItemTypeSupport研究了一下,写一篇博客总结一下。



先看一下这两张图,这其中使用的就是ListView(先用ListView,recycle我还不会。。。。)通过对adapter中不同的ItemType进行判断而采用不同的的布局文件

今日头条的那种其实就是有三种布局,根据新闻中图片的个数,或者其他的什么属性来判断采用哪种布局就可以实现这样不同的item的效果。当然,这些看起来好像有些复杂,对于没有写过聊天的更有些难度,不过大神们都给咱们写好了。直接用就可以。

1.MultiItemTypeSupport(用于对不同布局进行设置的辅助类--个人这么理解的。。)

<span style="font-size:18px;">public interface MultiItemTypeSupport<T>
{
	int getLayoutId(int position, T t);

	int getViewTypeCount();

	int getItemViewType(int position, T t);
}</span>

可以看出来,只有三个抽象方法,除了第一个剩下那两个如果之前使用过不同布局的童鞋应该很熟悉,getViewTypeCount获得的是所需要的不同布局的个数。

getItemViewType返回的是T中区分不同布局的值,getLayoutId返回的是不同的布局ID。

2.MultiItemCommonAdapter(大神写好的用于不同布局的adapter,我们要使用只需要继承这个adapter就可以)

<span style="font-size:18px;">public abstract class MultiItemCommonAdapter<T> extends CommonAdapter<T>
{

    protected MultiItemTypeSupport<T> mMultiItemTypeSupport;

    public MultiItemCommonAdapter(Context context, List<T> datas,
                                  MultiItemTypeSupport<T> multiItemTypeSupport)
    {
    	//因为不确定使用哪个layout所以返回-1
        super(context, -1, datas);
        mMultiItemTypeSupport = multiItemTypeSupport;
        if (mMultiItemTypeSupport == null)
            throw new IllegalArgumentException("the mMultiItemTypeSupport can not be null.");
    }

    @Override
    public int getViewTypeCount()
    {
        if (mMultiItemTypeSupport != null)
            return mMultiItemTypeSupport.getViewTypeCount();
        return super.getViewTypeCount();
    }

    @Override
    public int getItemViewType(int position)
    {
        if (mMultiItemTypeSupport != null)
            return mMultiItemTypeSupport.getItemViewType(position,
                    mDatas.get(position));
        return super.getItemViewType(position);

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        if (mMultiItemTypeSupport == null)
            return super.getView(position, convertView, parent);

        int layoutId = mMultiItemTypeSupport.getLayoutId(position,
                getItem(position));
        ViewHolder viewHolder = ViewHolder.get(mContext, convertView, parent,
                layoutId, position);
        convert(viewHolder, getItem(position));
        return viewHolder.getConvertView();
    }</span>

}

首先看一下构造方法,一个上下文,一个数据集这没有没有问题,第三个就是之前写的那个辅助类,用于设置布局类型的。

之后就是两个重写的方法,getItemViewType()和getViewTypeCount(),用于对adapter的布局类型进行设置,如果mMultiItemTypeSupport为空的话就使用父类中的设置。

最后是getView()方法 如果mMultiItemTypeSupport为空的话就直接使用conmmonadapter的getview,不为空的话,根据mMultiItemTypeSupport中的layoutid来决定使用哪个布局文件,创建对应的ViewHolder,convert方法直接写,因为也是抽象类,在new的时候回直接重写此方法。

3.应用,鸿洋大神写的demo,方便大家使用和理解一下,使用起来真是超爽的。

ChatAdapter

<span style="font-size:14px;">public class ChatAdapter extends MultiItemCommonAdapter<ChatMessage>
{
    public ChatAdapter(Context context, List<ChatMessage> datas)
    {
        super(context, datas, new MultiItemTypeSupport<ChatMessage>()
        {
            @Override
            public int getLayoutId(int position, ChatMessage msg)
            {
                if (msg.isComMeg())
                {
                    return R.layout.main_chat_from_msg;
                }
                return R.layout.main_chat_send_msg;
            }

            @Override
            public int getViewTypeCount()
            {
                return 2;
            }
            @Override
            public int getItemViewType(int postion, ChatMessage msg)
            {
                if (msg.isComMeg())
                {
                    return ChatMessage.RECIEVE_MSG;
                }
                return ChatMessage.SEND_MSG;
            }
        });
    }

    @Override
    public void convert(ViewHolder holder, ChatMessage chatMessage)
    {

        switch (holder.getLayoutId())
        {
            case R.layout.main_chat_from_msg:
                holder.setText(R.id.chat_from_content, chatMessage.getContent());
                holder.setText(R.id.chat_from_name, chatMessage.getName());
                holder.setImageResource(R.id.chat_from_icon, chatMessage.getIcon());
                break;
            case R.layout.main_chat_send_msg:
                holder.setText(R.id.chat_send_content, chatMessage.getContent());
                holder.setText(R.id.chat_send_name, chatMessage.getName());
                holder.setImageResource(R.id.chat_send_icon, chatMessage.getIcon());
                break;
        }
    }
</span>}

个人感觉在getview方法中可以直接赋值,如果两个布局文件中基本控件相同的话,并且所实现的功能也相同,那么可以采用相同的控件ID,不用Swith判断,直接使用viewholder赋值就可以,或者可以这样说,在不同的布局文件中如果有具有相同的功能的控件,就可以使用相同的id。直接赋值,不用对布局文件进行判断。

Activity

<span style="font-size:18px;">public class MultiItemListViewActivity extends AppCompatActivity
{

    private ListView mListView;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mListView = (ListView) findViewById(R.id.id_listview_list);
        mListView.setDivider(null);
        mListView.setAdapter(new ChatAdapter(this, ChatMessage.MOCK_DATAS));

    }
</span>
}

我是不是只复制一句话就可以?,就是这么简单。

4.总结

对于基本的listView,girdView的使用通用adapter基本没有问题,RecycleView的使用还差的远,不过有了这个通用的adapter之后,写代码只需要一行就可以搞定。确实实用 高效

下一篇估计会写关于view 的事件分发机制。recycelview估计还得等等。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值