背景:
做IM聊天,对接其他部门业务需求,老是接到需要定制个性化的消息UI,接手这块业务时候,以前的代码写的比较死,怎么样的呢:
一个BaseAdapter,包含2个view (RecvView,SendView)
每次来消息不断的根据消息类型去隐藏和显示已经在xml中配置好的view样式。
比较坑吧,不仅绑定的死死的,没法扩展,就是看也很难看懂,不断的在view中if-else判断消息类型,处理消息显示/隐藏。
下定决心,抽空思考了一番,决定抽象块内容,把view与adapter分离
经过一个星期在做完白天工作之余,完成了下面的设计与编码工作:
UML设计类图:
详细介绍:
从上面设计图可以看出主要分为4个部分:
- Adapter:通过MsgViewBehavior接口绑定ItemView
- Holder: 消息View的显示与数据绑定
- TypeToHolder:处理view Type 与缓存holder的关系
- WrapperToType:处理消息数据与view Type关系
Adapter绑定消息View:
可以看到BaseAdpter与view没有直接的关联,通过MsgViewBehavior.bindView(xxx)来绑定对应的消息类型的UI,MsgViewProxyImpl实现了MsgViewBehavior接口的bindView方法;
MsgViewProxyImpl.java
public View getBindView(View convertView, int position, MessageWrapper wrapper, int msgViewType) {
if (wrapper == null || wrapper.msg == null) {
return convertView;
}
BaseMsgHolder holder;
//ListView holder缓存机制实现消息item复用
if (shouldCache(convertView, viewType, wrapper.isSend) && convertView.getTag() instanceof BaseMsgHolder) {
holder = (BaseMsgHolder) convertView.getTag();
} else {
//viewType --> holder
holder = mTypeToHolderBehavior.getViewHolder(viewType);