ListView和Adapter的基础知识html
【问】假如Listview的item数量有10亿条的话岂不是要绘制10亿个View?java
【答】确定不可能,手机内容会没那么大...Android针对这种状况专门设计了Recycler的构件缓存
【参考】http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.htmlide
【概要】布局
假如一个页面只能显示10条list内容,且每一个条目的样式是同样的spa
那么50条内容的显示,其实只是1~10条会绘制页面 [ convertView仍然是空值 ]设计
if (convertView == null) { convertView = mInflater.inflate(R.layout.item1, null); holder = new ViewHolder(); holder.textView = (TextView)convertView.findViewById(R.id.text); convertView.setTag(holder); }
当编号为1的条目向上滑动移出屏幕以后[View-1]code
编号为11的条目自下进入屏幕,将会直接套用[View-1]orm
else { holder = (ViewHolder)convertView.getTag(); }
看看代码
htm
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; // 提升刷新的效率,避免卡顿 // 当子条目容器为空的时候,填充布局式样 if (convertView == null) { convertView = LayoutInflater.from(mContext).inflate( R.layout.adapter_circle_msg_item, null); holder = new ViewHolder(convertView); // setTag的妙用 // 绑定convertView与ViewHolder贴上Tag convertView.setTag(holder); } else { // setTag的妙用 // 当convertView非空时候,直接根据Tag拿到绑定的ViewHolder【存放在缓存中的】 holder = (ViewHolder) convertView.getTag(); } CircleMsgItemInfo info = mInfos.get(position); holder.fillViewWithData(info); return convertView; }
代码解析
setTag方法是干什么的?
setTag给View对象的一个标签,标签能够是任何内容,咱们这里把他设置成了一个对象
ViewHolder holder; ... convertView.setTag(holder);
由于咱们先抽象出来成为一个内部类ViewHolder,用了setTag,这个标签就是ViewHolder实例化后对象的一个属性。
咱们以后对于ViewHolder实例化的对象holder的操做,都会由于java的引用机制而一直存活并改变convertView的内容,而不是每次都是去new一个,而达到重用的效果。
不使用Tag标签会怎么样呢?
第一种状况:当UI容器没用使用LayoutInflater进行View填充的时候,不必使用。
第二种状况:当UI容器使用LayoutInflater进行View填充的时候,不使用Tag机制会形成滑动卡顿
使用Tag的必要性?
当ListView中每个item的布局都不同的时候,就不须要使用Tag
Tag标志是为了,提交重用的目的拟出的,没有一样的布局就没有意义了
Listview滑动UI显示异常的问题
【1】显示顺序异常的问题1-2-3-4-5-6-7-8,滑动以后可能变成2-3-4-5-6-7-8-1?
该问题在我工程中遇到的问题具备特殊性:一共只有8个item条目,且每一个布局都不同
问题处理:取代哦setTag的逻辑
【2】滑动后页面显示异常,A条目的内容可能跟B条目的内容混杂在一块儿
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { ... convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } CircleMsgItemInfo info = mInfos.get(position); holder.fillViewWithData(info); return convertView; } public void fillViewWithData(CircleMsgItemInfo info) { showHeaderBackground(info.getReplyHeadImg()); name.setText(info.getReplyName()); if (info.getReplyType().equals("like")) { content.setText(R.string.friend_circle_like); content.setTextColor(mContext.getResources().getColor( R.color.blue_95)); TextPaint tp = content.getPaint(); tp.setFakeBoldText(true); } else { content.setText(EmojiUtil.formatEmoji(mContext, info.getReplyContent())); content.setTextColor(mContext.getResources().getColor( R.color.black)); TextPaint tp = content.getPaint(); tp.setFakeBoldText(false); } time.setText(FriendlyDateFormat.formatTime(info.getReplyTime())); }
这是因为Android回收机制致使的,由于设置重用,避免单条View的从新绘制。
fillViewWithData在填充数据的时候,若是没有将item每个内容都重写一遍的话,遗漏的部分将使用以前item中的内容
事例:
item Old data : A B C D E
item New date : a c d e {注意没有 b }
那么显示的效果 : a B c d e