经过昨天一天的尝试与上午的一些努力,通用的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估计还得等等。