在看了一些vogella的文章之后,发现关于android listview性能优化这一段很有意思,于是实践了一下,经过优化,性能确实提升不少!
先看看优化前和优化后的比较:
优化前的log截图:
优化后的log截图:
并且,在不停滚动ListView的过程中,优化之前会出现ANR现象,在AVD上特别容易复现:
然后,优化后显得很流畅,附上对于的log截图:
下面附上相关代码分析:
ListView中的每一个Item由一个ImageView 和一个TextView组成
Layout:
" Activity继承自ListActivity,我故意增加了Item,方便测试,效果更明显:
publicclassListViewDemoextendsListActivity{ privatefinalString[]mItems=newString[]{"Android","iPhone", "WindowsMobile","Blackberry","WebOS","Ubuntu","Windows7", "MaxOSX","Linux","OS/2","Ubuntu","Windows7","MaxOSX", "Linux","OS/2","Ubuntu","Windows7","MaxOSX","Linux","OS/2", "Ubuntu","Windows7","MaxOSX","Linux","OS/2","Ubuntu", "Windows7","MaxOSX","Linux","OS/2","Ubuntu","Windows7", "MaxOSX","Linux","OS/2","Ubuntu","Windows7","MaxOSX", "Linux","OS/2","Ubuntu","Windows7","MaxOSX","Linux","OS/2", "Ubuntu","Windows7","MaxOSX","Linux","OS/2","Ubuntu", "Windows7","MaxOSX","Linux","OS/2","Ubuntu","Windows7", "MaxOSX","Linux","OS/2","Ubuntu","Windows7","MaxOSX", "Linux","OS/2","Ubuntu","Windows7","MaxOSX","Linux","OS/2", "Ubuntu","Windows7","MaxOSX","Linux","OS/2","Ubuntu", "Windows7","MaxOSX","Linux","OS/2","Ubuntu","Windows7", "MaxOSX","Linux","OS/2","Ubuntu","Windows7","MaxOSX", "Linux","OS/2","Ubuntu","Windows7","MaxOSX","Linux","OS/2", "Ubuntu","Windows7","MaxOSX","Linux","OS/2","Ubuntu", "Windows7","MaxOSX","Linux","OS/2","Ubuntu","Windows7", "MaxOSX","Linux","OS/2","Ubuntu","Windows7","MaxOSX", "Linux","OS/2","Ubuntu","Windows7","MaxOSX","Linux","OS/2", "Ubuntu","Windows7","MaxOSX","Linux","OS/2","Ubuntu", "Windows7","MaxOSX","Linux","OS/2","Ubuntu","Windows7", "MaxOSX","Linux","OS/2","Ubuntu","Windows7","MaxOSX", "Linux","OS/2","Ubuntu","Windows7","MaxOSX","Linux","OS/2", "Ubuntu","Windows7","MaxOSX","Linux","OS/2","Ubuntu", "Windows7","MaxOSX","Linux","OS/2","Ubuntu","Windows7", "MaxOSX","Linux","OS/2","Ubuntu","Windows7","MaxOSX", "Linux","OS/2","Ubuntu","Windows7","MaxOSX","Linux","OS/2"}; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); ListViewArrayAdapteradapter=newListViewArrayAdapter(this,mItems); getListView().setAdapter(adapter); } }然后custom Adapter,优化之前的adapter:
@Override publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ longstart=System.currentTimeMillis(); LayoutInflaterinflater=(LayoutInflater)mContext.getLayoutInflater(); ViewrowView=inflater.inflate(mViewResourceId,parent,false); TextViewtextView=(TextView)rowView .findViewById(mTextViewResourceId); ImageViewimageView=(ImageView)rowView .findViewById(mImageViewResourceId); textView.setText(mNames[position]); Strings=mNames[position]; if(s.startsWith("Windows7")||s.startsWith("iPhone")){ imageView.setImageResource(R.drawable.no); }else{ imageView.setImageResource(R.drawable.yes); } Log.v("jerikc","costtime="+(System.currentTimeMillis()-start)); returnrowView; }优化之后的Adapter:
publicclassListViewArrayAdapterextendsArrayAdapter{ privatefinalActivitymContext; privatefinalString[]mNames; privatefinalstaticintmViewResourceId=yout.text_image_row_layout; privatefinalstaticintmTextViewResourceId=R.id.textView; privatefinalstaticintmImageViewResourceId=R.id.imageView; staticclassViewHolder{ publicTextViewtext; publicImageViewimage; } publicListViewArrayAdapter(Activitycontext,String[]names){ super(context,mViewResourceId,names); this.mContext=context; this.mNames=names; } @Override publicViewgetView(intposition,ViewconvertView,ViewGroupparent){ longstart=System.currentTimeMillis(); ViewrowView=convertView; if(rowView==null){ LayoutInflaterinflater=mContext.getLayoutInflater(); rowView=inflater.inflate(mViewResourceId,null); ViewHolderviewHolder=newViewHolder(); viewHolder.text=(TextView)rowView.findViewById(mTextViewResourceId); viewHolder.image=(ImageView)rowView.findViewById(mImageViewResourceId); rowView.setTag(viewHolder); } ViewHolderholder=(ViewHolder)rowView.getTag(); Strings=mNames[position]; holder.text.setText(s); if(s.startsWith("Windows7")||s.startsWith("iPhone")){ holder.image.setImageResource(R.drawable.no); }else{ holder.image.setImageResource(R.drawable.yes); } Log.v("jerikc","costtime="+(System.currentTimeMillis()-start)); returnrowView; } }优化的大致思想就是:优化之前,每次加载item的时候,都要加载一下布局文件,然后生成一个新的row View对象,然后通过View找到对应的ImageView和TextView,正如我们所知道的那样,加载布局文件时很耗时的,特别是在操作比较频繁 情况下,这是不可忍受的,所以会导致ANR现象。
因此,我们可以重复利用已不可见的row View对象。Android中,当它决定让row View对象不可见的时候,它允许通过getView方法中的convertView参数来重复利用刚刚不可见的row View对象。
在优化的过程中,第一次加载的时候,我们需要把相关的数据保存起来,而View有一个方法setTag,该方法可用来保存一些数据结构。我们一个row View对象是由ImageView和TextView空间组成的,因此定义一个ViewHolder来保存ImageView和TextView对象。 在重复利用的过程中,只需简单修改它们的值,而不用再次findViewById。