发现这个问题的起因是:服务端同事说最近日志平台出现了很多请求图片错误的日志,看ua信息判断是我们Android客户端请求的,是同一张错误图片,且请求频率很高(同一用户1s内请求很多次)。
后续排查发现,是GridView捣的鬼。
1、首先是我们功能中有一个是GridView实现的,item布局中包含ImageView,会加载服务端提供的图片;
2、第1条数据的图片存在问题,请求失败;
3、GridView存在反复调用position=0的getView()的问题,导致该功能页面展示时,会多次刷新第0个item布局,多次加载这张问题图片,也就出现高频次请求该问题图片的情况;
GridView之所以存在反复调用position=0的getView()的问题,是因为:GridView需要measure自身的高度,但并不会去遍历所有子view,而是直接将position=0的子view作为模板,取其布局尺寸,这样也就导致position=0的getView被多次调用,具体代码可参考GridView#onMeasure()->obtainView(0)。
解决:从改动性最小角度出发,将无效的getView(0)进行过滤,保证一次刷新,每项item都只会调用一次getView()。
1、封装一个adapter,去完成过滤0操作。
public abstract class FilterZeroAdapter extends BaseAdapter{
protected int lastPosition = -1;
@Overide
public View getView(int position, View convertView, ViewGroup parent){
if(getCount()>1){
if(lastPosition == 0 && position == 0 && convertView != null){
return convertView;
}
}
lastPosition = position;
return getViewInner(position, convertView, parent);
}
public abstract View getViewInner(int position, View convertView, ViewGroup parent);
}
2、修改现有GridView所使用的Adapter,只需要改动两处:
1)、修改继承类,将原BaseAdapter改为上面封装的FilterZeroAdapter,如:MyAdapter extends BaseAdapter ==》MyAdapter extends FilterZeroAdapter ;
2)、修改刷新布局方法,将原getView()方法改为getViewInner,如:getView() ==》getViewInner();