浅谈ListView之convertView和viewHolder

原创 2016年08月30日 18:42:09
最近开发相册时,碰到缩略图显示的问题,功能实现后发现滚动时比较的卡顿,
先就ListView优化问题提出几点看法:
1、复用已经生成的convertView;
2、添加viewHolder类;
3、缓存数据(图片缓存);
4、分页加载。

1、convertView的复用

ListView的原理:ListView中的每一个Item显示都需要Adapter调用一次getView的方法,这个方法会传入一个convertView的参数,返回的View就是这个Item显示的View。如果当Item的数量足够大,再为每一个Item都创建一个View对象,必将占用很多内存,创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)也是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环器)的构件,就是当ListView的Item从上方滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会从下方生成一个Item,而此时调用的getView中的convertView参数就是滚出屏幕的Item的View,所以说如果能重用这个convertView,就会大大改善性能。

<span style="background-color:rgb(204,204,204)">BaseAdapter适配器里有个getView()需要重写
public View getView(int position,View converView,ViewGroup parent)  {  //省略。。。。。。}</span>
这个convertView其实就是最关键的部分  原理上讲 当ListView滑动的过程中 会有item被滑出屏幕 而不再被使用 这时候Android会回收这个条目的view 这个view也就是这里的convertView。<pre name="code" id="best-content-1572584631" class="best-text mb-10" style="margin-top:0px; margin-bottom:10px; padding:0px; font-family:arial,'courier new',courier,宋体,monospace; white-space:pre-wrap; word-wrap:break-word; background-color:rgb(241,254,221)">当item1被移除屏幕的时候 我们会重新new一个View给新显示的item_new 而如果使用了这个convertView 我们其实可以复用它 这样就省去了new View的大量开销。


public View getView(int position, View convertView, ViewGroup parent) {
	View view = null;
	if (convertView != null) {
	view = convertView;
	//复用了回收的view 只需要直接作内容填充的修改就好了
	} else {
	view = new Xxx(...);
	//没有供复用的view 按一般的做法新建view
	}
	return view;
}

小demo:

static class ViewHolder
	{				
		public TextView mSelectAlbumName;
		public MyImageView mAlbumView;
		private TextView mImageCounts;
	}	
这里,static关键字的作用就是保证该类在内存中只有一个对象,也就是只有一块内存空间,所以不会ViewHolder holder = new ViewHolder()一次就会开辟一块新地址的,不管new几次,都是指向第一次new时开辟的地址,所有引用共用这一地址,即节省内存、又提高效率。


@Override
	public View getView(int position, View convertView, ViewGroup parent)
	{
	    final ViewHolder viewHolder;
	    String path = albumList.get(position).getPhotoList().get(0).getPath();
        if (convertView == null) 
        {   
        	viewHolder = new ViewHolder();
        	convertView = mInflater.inflate(R.layout.select_album_grid_item, null);		       	
        	viewHolder.mSelectAlbumName = (TextView)convertView.findViewById(R.id.txtSelectName);
        	viewHolder.mAlbumView = (MyImageView)convertView.findViewById(R.id.imgAlbum);    
        	viewHolder.mImageCounts = (TextView)convertView.findViewById(R.id.group_count);       	
        	viewHolder.mAlbumView.setOnMeasureListener(new OnMeasureListener() {
  				
  				@Override
  				public void onMeasureSize(int width, int height) {
  					mPoint.set(width, height);
  				}
  			});
        	convertView.setTag(viewHolder);            
        }  
        else { 
        	viewHolder = (ViewHolder) convertView.getTag(); 
        } 
		
        viewHolder.mSelectAlbumName.setText(albumList.get(position).getName());
        viewHolder.mImageCounts.setText(albumList.get(position).getCount()+" "+context.getString(R.string.pictures));
        viewHolder.mAlbumView.setTag(path);       
        Bitmap bitmap = ImageLoader.getInstance().loadNativeImage(path, mPoint, new NativeImageCallBack()
        {
			@Override
			public void onImageLoader(Bitmap bitmap, String path) {			
			ImageView mImageView = (ImageView)mGridView.findViewWithTag(path); 
			if(bitmap != null && mImageView != null) {
				mImageView.setImageBitmap(bitmap);
			}
		   }
        });
        
        if(bitmap != null) {
        	 viewHolder.mAlbumView.setImageBitmap(bitmap);
        }
        return convertView; 
	}

2、viewHolder类的使用

        在getView方法中的操作是这样的:先从xml中创建view对象(inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,找到每一个子View,如:一个TextView等。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用viewHolder,把每一个子View都放在Holder中,当第一次创建convertView对象时,把这些子view找出来。然后用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。当第二次重用convertView时,只需从convertView中getTag取出来就可以了。

setTag()(设置标签)是将view封装起来,以便下次复用,getTag()(获取标签)是得到封装的view。

版权声明:本文为博主原创文章,未经博主允许不得转载。

安卓开发,listview的优化,减少内存消耗,复用convertView、ViewHolder和分页加载

1:复用convertView,可以减少view对象的创建。adapter中的getview()方法会传经来一个convertView,convertView是指曾经使用过的view对象,可以被重复使...

ListView中ConvertView和ViewHolder

ListView中ConvertView和ViewHolder

ListView中convertview和ViewHolder的区别

LsitView和Adapter 参考:http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html 工作原理:  1.Lis...

ListView(优化),自定义Layout和adapter,entity,ViewHolder,ConvertView用法案例(phone)

自定义实体类:PhoneEntity.javapackage com.example.entity;/** * Created by Administrator on 2017/2/16. */p...

ListView中convertView和ViewHolder的工作原理

LsitView和Adapter参考: http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html 工作原理: 1.Lis...

convertView优化ListView性能 ViewHolder中介 Github 简明入门指南思维导图

这里提到的ListView只是作为一个典型代表 其实在Android中 采用类似Adapter机制的GridView等都是可以适用的 而ListView应该是用得最多的 所以就以它来举例 大家都知道...

ListView性能优化之convertView和ViewHolder

最近碰到的面试题中经常会碰到问"ListView的优化"问题。所以就拿自己之前写的微博客户端的程序做下优化。 自己查了些资料,看了别人写的博客,得出结论,ListView优化大致从以下几个角度: ...

探秘ListView的ConvertView以及ViewHolder原理

转自:http://zhiweiofli.iteye.com/blog/1269746 最近在使用android的组件ExpandableListView,实现需求时,遇到不少奇怪的问题。 ...
  • cc_lq
  • cc_lq
  • 2011年12月21日 09:04
  • 1556

ListView为什么要使用convertView和ViewHolder

原因就是: 1. 使用convertView可以避免重复地调用inflate 2. 使用ViewHolder可以避免重复地调用findViewById 下面的getVie...

ListView的性能优化之convertView和viewHolder

参考:http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html 最近碰到的面试题中经常会碰到问"ListView的优化"问...
  • FJim305
  • FJim305
  • 2014年05月14日 22:50
  • 615
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:浅谈ListView之convertView和viewHolder
举报原因:
原因补充:

(最多只允许输入30个字)