需求:
- 手指快速滑动后抬起,在listview自由滑动状态下不对图片进行网络请求与绘制
- 手指拖拽滑动,正常请求图片并绘制
目的:
- 用户快速滑动listview,说明用户对这部分数据不关心,对于用户不关心的数据不进行网络请求,节省流量。
与新浪微博快速滑动不加载图片效果类似
实现:
首先是对listview添加监听,有setOnScrollListener
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
/**
*监听着ListView的滑动状态改变。
* SCROLL_STATE_TOUCH_SCROLL:手指正拖着ListView滑动
* SCROLL_STATE_FLING:ListView正自由滑动
* SCROLL_STATE_IDLE:ListView滑动后静止
* */
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
/**
* firstVisibleItem: 在屏幕中第一条显示的数据在数据源中的索引
* visibleItemCount:屏幕中共有几个item
* totalItemCount 数据源中数据的总个数
* */
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
}
在判断listview处于SCROLL_STATE_TOUCH_SCROLL状态时 正常加载图片
处于SCROLL_STATE_FLING状态时不加载图片
处于SCROLL_STATE_IDLE状态时加载当前屏幕上的所有item的图片
在Adapter中定义一个成员变量记录当前滑动状态,根据此状态来判断是否要在getview中加载图片。此时出现一个问题,自由滑动状态静止后,当前屏幕的item中的数据被判断为自由滑动状态而没有被加载,解决此问题的方案是在SCROLL_STATE_IDLE此状态下手动调用getview方法,让当前屏幕的图片加载。
先来看一下getview需要传的参数
public View getView(int position, View convertView, ViewGroup parent)
position 数据在数据源中的索引,convertView 复用的view,parent 父容器
循环getview当前屏幕上所有的item,从firstVisibleItem开始,共visibleItemCount次
在监听接口中的onScroll方法记录firstVisibleItem与visibleItemCount。onScroll方法是每次在滑动出现下一个item时调用
//在SCROLL_STATE_IDLE状态下
for(int i=0;i<mvisibleItemCount;i++){
//返回当前屏幕上item对应的convertview
View itemView = view.getChildAt(i);
adapter.getView(mfirstVisibleItem+i,itemView,listView);
}
这样就实现了不对自由滑动的item中的图片进行网络请求
但是这样还有一个缺陷:如果是加载过的图片,已经请求过网络,保存在内存中,但是在自由滑动的时候不绘制,用户体验不佳
解决办法是在adapter中保存一份已加载过的图片的url集合,在进行判断滑动状态之前判断这个图片是否加载过,如果加载过直接绘制,没加载过在进行滑动状态的判断。
主要代码:
//Activity中
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState==SCROLL_STATE_TOUCH_SCROLL){
adapter.setState(true);
}
if(scrollState==SCROLL_STATE_FLING){
adapter.setState(false);
}
if(scrollState==SCROLL_STATE_IDLE){
adapter.setState(true);
for(int i=0;i<mvisibleItemCount;i++){
View itemView = view.getChildAt(i);
//手动调用getview
adapter.getView(mfirstVisibleItem+i,itemView,view);
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
//两个成员变量
mfirstVisibleItem = firstVisibleItem;
mvisibleItemCount=visibleItemCount;
}
});