ListView的优化问题是安卓面试中的常客,我记得我自己在不少次面试被问到有哪几种方法可以优化ListView的性能
convertView的使用,主要优化加载布局问题
listivew每次滚动都会调用gitview()方法,所以优化getView是重中之重。
如果没有缓存就加载布局,如果有缓存就直接用convertView对象。所以这样就不用滑动listview的时候调用getView()方法每次都去加载布局了(如果改布局已经加载)
if(convertView == null) { convertView = LayoutInflater.from(mContext).inflate(R.layout.feeds_main_item,null); holder = new ViewHolder(); holder.mTextView = (TextView)convertView.findViewById(R.id.main_text); holder.mPic = (SimpleDraweeView)convertView.findViewById(R.id.pic); convertView.setTag(holder); }else{ holder = (ViewHolder)convertView.getTag(); }
2. 内部类ViewHolder的使用
主要优化getView方法中每次回调用findviewByID()方法来获取一次控件的代码,新增加内部类ViewHolder,用于对控件的实力存储进行缓存。
convertView为空时,viewHolder会将控件的实例存放在ViewHolder里,然后用setTag方法讲viewHolder对象存储在view里。
convertView不为空时,用getTag方法获取viewHolder对象.
class ViewHolder{ public TextView mTextView; public SimpleDraweeView mPic; }
3. RecycleBin机制
这个是保证ListView有非常多数据滚动时也不会发生oom错误的基础
listview的许多view呈现在Ui上,这样的View对我们来说是可见的,可以称为OnScreen的view(也为ActionView)。
view被上滚移除屏幕,这样的view称为offScreenView(也称为ScrapView)。
然后ScrapView会被listview删除,而RecycleView会将这部分保存。
而listview底部需要显示的view会从RecycleBin里面取出一个ScrapView。
将其作为convertView参数传递过去,从而达到View复用的目的,这样就不必在Adapter的getView方法中执行LayoutInflater.inflate()方法了
在RecycleBin里面有两个数组,Actionview和ScrapViews.
private View[] mActiveViews = new View[0]; private ArrayList<View>[] mScrapViews;