今天学习了list的自定义适配器,本以为能够把view以及对应的数据全都存放在listview就万事大吉了,但是没考虑到一点,那就是内存的使用问题,当我们使用getview不停得加载listview中数据时,有一段代码是不断重复执行的,那就是我们对应的搜索空间的代码
当我们使用convertview来进行自定义布局时,我们有一点是不知道的,听我慢慢讲解:public View getView(int position, View convertView, ViewGroup parent) { convertView= LayoutInflater.from(context).inflate(R.layout.listview,null); textdate=(TextView) convertView.findViewById(R.id.textdate); texttitle= (TextView) convertView.findViewById(R.id.texttitle); textmain= (TextView) convertView.findViewById(R.id.textmain); textid= (TextView) convertView.findViewById(R.id.text_id); textdate.setText(infos.get(position).getYear()+"-"+infos.get(position).getMonth()+"-"+infos.get(position).getDay()); texttitle.setText(infos.get(position).getTitle()); textmain.setText(infos.get(position).getMain()); textid.setText(Integer.toString(infos.get(position).getId())); return convertView; }
假顶我们的手机屏幕高度为100,listview中的item高度为10,
那么我们的手机屏幕最多能够同时容纳10个item,而当第1次打开activity的时候,系统自动加载了1-10 的item进去
textdate=(TextView) convertView.findViewById(R.id.textdate); texttitle= (TextView) convertView.findViewById(R.id.texttitle); textmain= (TextView) convertView.findViewById(R.id.textmain); textid= (TextView) convertView.findViewById(R.id.text_id);那么,对于搜寻控件的代码来说,是不是至少执行了10次?
因为每一个item创建的时候,都会执行一次。
OK那么当我们滑动屏幕,第11个view加载进来进来的时候,第一个view有一半超出屏幕上方,只有下半部分还留在屏幕内
这个图片只是例子,大家可以看到,屏幕最上面的数字1,还有半个在屏幕内,屏幕最底部,42有半个进入屏幕,但是还没有完全进入屏幕,那么这个时候,承载42的view也是系统新创建的,
那么当1完全退出屏幕,而42完全进去以后,承载1的concertview就会空出来,他会跑到屏幕最下面,去做承载43的容器,即把view里面的内容从1换成43然后又从屏幕底部露出来,这样节省了再次为43重启搜索一次控件的开销。
当然当item数量少的时候,这样做效果不明显,但是如果当item数量有1万条的时候呢,那么我们就可以节约1万次通过findviewbyid来查找控件,运行效率就大大增加了。
那么是如何实现的呢:
其实就是定义了一个静态内部类 viewholder,将搜索到的view全部存到这个类当中,因为是静态的,那么可以跟类一起保存下来,不用多次寻找
static class ViewHodler{ TextView texttitle,textdate,textmain,textid; }
其实单独看这个还是看不出什么问题,那么我放出整段的代码
public View getView(int position, View convertView, ViewGroup parent) { ViewHodler vh; if(convertView==null){ convertView= LayoutInflater.from(context).inflate(R.layout.listview,null); vh=new ViewHodler(); vh.textdate=(TextView) convertView.findViewById(R.id.textdate); vh.texttitle= (TextView) convertView.findViewById(R.id.texttitle); vh.textmain= (TextView) convertView.findViewById(R.id.textmain); vh.textid= (TextView) convertView.findViewById(R.id.text_id); convertView.setTag(vh); }else{ vh= (ViewHodler) convertView.getTag(); } vh.textdate.setText(infos.get(position).getYear()+"-"+infos.get(position).getMonth()+"-"+infos.get(position).getDay()); vh.texttitle.setText(infos.get(position).getTitle()); vh.textmain.setText(infos.get(position).getMain()); vh.textid.setText(Integer.toString(infos.get(position).getId())); return convertView; } static class ViewHodler{ TextView texttitle,textdate,textmain,textid; } }这是整体的代码,
主要是通过
convertView.setTag(vh);
来实现将vh对象存储起来,方便我们下次使用,当我们第一次创建view的时候,搜索控件,然后就把搜索的结果存到了静态的viewholder中,那么下一次继续使用就不需要再去寻找了。