第一(优化加载布局:
重用了convertView,很大程度上的减少了内存的消耗。通过判断convertView是否为null,是的话就需要产生一个视图出来,然后给这个视图数据,最后将这个视图返回给底层,呈献给用户。
特点:如果当前的convertView为null,则通过LayoutInflat产生一个view。
代码如下
View view;
if(convertView == null){
view = LayoutInfalter.from(getContext()).inflate(resourceID,null)
}
else{
view = convertView
}
LayoutInfalter.from(getContext()).inflate(resourceID,null)
,LayoutInflater.from(Context).inflater是用于那些未被加载的界面的类似注册的方法,resourceID就是这个界面的布局文件
第二.(可(在第一步下再优化一次,优化加载控件)可解决异步加载图片错乱问题:
主要优化getView方法中每次回调用findviewByID()方法来获取一次控件的代码,不同重复注册控件。
新增加内部类ViewHolder,用于对控件的实例存储进行缓存。
- convertView为空时,viewHolder会将空间的实力存放在ViewHolder里,然后用setTag方法讲viewHolder对象存储在view里。
- convertView不为空时,用getTag方法获取viewHolder对象.
- 最后再讲viewholder对象中的控件取出并给他们赋值
{public View getView(...,View convertview,...){
class ViewHolder{
ImageView image;
}
View view;
ViewHolder holder;
if(convertview==null){
view=Layoutinflater.from(getContext()).inflater(resourceID,null);
holder=new ViewHolder();
holder.image=(ImageView)view.findid....;
view.setTag(holder);
}
else{
view=convertview;
holder=(ViewHolder)view.getTag();
}
holder.image=view.setImageres(int id);
}
return view;
}
因为异步加载的时候,由于recyclebin机制,上滑出界面的那个item7会被复用到准备进入的那个item0,但是对应异步的数据被填充到item0造成了数据的错乱;
可通过setTag getTag解决该问题;
第三.快速滑动时,不加载图片(异步加载)
当用户快速滑动的时候,应用程序正在下载图片,此时应该停止加载图片,保证滑动的流畅性;当滑动停止时再加载图片。这种方式的效果很明显。
google提出来的示例代码:
- public void onScrollStateChanged(AbsListView listView, int scrollState) {
- // Pause disk cache access to ensure smoother scrolling
- if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
- imageLoader.stopProcessingQueue();
- } else {
- imageLoader.startProcessingQueue();
- }
- }
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- // TODO Auto-generated method stub
- }
第四。分页加载
数据量大的时候不能一次将数据加载完成,需要进行分页加载;
3.(不是优化方案了
ListView加载成千上万的数据为什么不出OOM错误?
最主要的是因为RecycleBin机制(两级缓存,ActiveView缓存+ScrapView缓存)
- listview的许多view呈现在Ui上,这样的View对我们来说是可见的,可以称为ActiveView.
- view被上滚移除屏幕,这样的view称为ScrapView
- 然后ScrapView会被listview删除,而RecycleBin会将这部分保存。
- 而listview底部需要显示的view会从RecycleBin里面取出一个ScrapView。
scapview:缓存了在屏幕外边的itemview,在进入屏幕的时候通过getView拿到缓存的itemview;
也就是说,当元素0完全移除屏幕时,元素7会获取item0的缓存,因此加载元素7的时候convertview!=null,后面也是同样的