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