[置顶] listview的onmeasure方法

时间:2022-09-22 18:56:33

大家都知道listview的格式是一定的而数据源确是多重多样的这时候就需要一种适配器来把数据源转换成listview要显示的格式baseAdapter就诞生了。再说onmeasure之前必须说说listview的缓存机制。大家都知道屏幕的大小是有限的 可是listview中的数据却可能很多 所以手机不能一下子展示所有的数据 它只会加载屏幕上显示的数据 。

如上图,当我们把屏幕往下滑动时 item1回收到recycler 而item8要显示在屏幕上 item8从recycler取出这样一个布局文件 并重新设置好item8要显示的数据 并设置要要显示的位置。总之一句话 需要才显示 显示完就被回收到缓存。

public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.advertise_item, parent, false);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.image);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
imageLoader.displayImage(mImg.get(position % mImg.size()), holder.image, options);
return convertView;
}

class ViewHolder {
public ImageView image;
}
代码住需要注意if判断 虽然只是一个if判断  但是 通过这个判断 可以避免创建大量的contentview对象 节省了大量的时间 利用了ListView的缓存特性 如果没有缓存才创建新的view 对getview方法进行了非常好的优化  但这仅仅只算入门,因为findViewById依然会浪费大量的时间 所以我们称这种方法为普通式。

提高版就是对findViewById的优化了 把findViewById 也放入if判断语句中 就ok了

我们需要创建一个内部类 里面有三个成员变量 都是我们item.xml文件中的三个控件 

通过viewHolder.setTag()方法 把viewHolder和contentView关联在一起 然后通过getTag方法得到viewHolder

这种方法不仅利用了listview的缓存,更通过viewHolder来实现显示视图的缓存,避免多次使用findViewById方法

作为一个有情怀的程序员 这才是最文艺的写法~

内存机制说清楚之后,就会产生一个问题,当我们由于项目业务需要,不希望listview缓存的时候怎么办呢?比如需要获取到listview的总数来进行下一步的计算等。当listview翻页之后,item又从0开始了,这时候之前的item内存已经被回收,如果我们需要获取的话就做不到了,这时候就需要onmeasure方法。代码如下:

if (parent instanceof ListViewForScrollView) {
if (((ListViewForScrollView) parent).isOnMeasure) {
convertView = LayoutInflater.from(context).inflate(res, null);
viewholder = new ViewHolder();
viewholder.jia = (ImageButton) convertView.findViewById(R.id.imageButtonJia2);

convertView.setTag(viewholder);
} else {
final ShopCar shopcar = list.get(position);
Log.i("position", String.valueOf(position));
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(res, null);
viewholder = new ViewHolder();
viewholder.jia = (ImageButton) convertView.findViewById(R.id.imageButtonJia2);

convertView.setTag(viewholder);
} else {
viewholder = (ViewHolder) convertView.getTag();
}

listviewforscroller代码如下

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
Log.i("onMeasure", "onMeasure");
isOnMeasure=true;
super.onMeasure(widthMeasureSpec, expandSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
Log.i("onLayout", "onLayout");
isOnMeasure=false;
super.onLayout(changed, l, t, r, b);

}
至于具体的onmeasure与onLayout方法的原理涉及到android的视图渲染控件,不是本篇重点也与开发无关,咱不介绍。