通用Adapter的嘗試《第二篇》

經過昨天一天的嘗試與上午的一些努力,通用的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估計還得等等。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章