问题

最近在项目中遇到过一个很棘手的问题,就是ListView在滑动后就莫名其妙的显示错乱,网上查阅资料后问题很容易的就解决了,但是对于问题产生的原因仍是一知半解,所以不甘心的我定下心来,狠读源码,终于理清了其中的”奥秘“。

由来

一般的关于Adapter中getView的写法不外乎以下形式:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder; if (convertView == null) {
convertView = mLayout.inflate(R.layout....);
holder = new ViewHolder();
holder.textView = (TextView) convertView
.findViewById(R.id.textview);
... ...
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textView.setText(mText + position);
return convertView;
}

在Android源码中关于getView方法的实现就是采用的以上形式,如ArrayAdapter等。因为这种写法的好处也是显而易见的,如果该position的convertview曾经被加载过,在数据集合未被改动的前提下,系统会自动将该position的convertview缓存起来,避免重复加载耗费资源。

然后问题就来了,当时我就”自作小聪明“,觉得当convertview==null时只是做了item布局的加载以及相关控件ID的绑定操作,为什么连内容的加载操作也放入其中呢,这样下次加载缓存是就省去内容set的操作了,然后就出现了滑动ListView后数据显示错位的问题-。-。

原因

后来看源码发现,原来AbListView中获取getView()和滑动操作是异步进行的,其中滑动操作在一个FlingRunnable的支线程中运行,所以这就导致了在ListView在滑动时可能已经滑动到了第十行,但可能第二行的数据这时就被直接使用了,这就是导致数据加载错乱的根本原因。

附上源码中对FlingRunnable的注释:

/**
* Responsible for fling behavior. Use {@link #start(int)} to
* initiate a fling. Each frame of the fling is handled in {@link #run()}.
* A FlingRunnable will keep re-posting itself until the fling is done.
*
*/
private class FlingRunnable implements Runnable {
/**
* Tracks the decay of a fling scroll
*/
private final OverScroller mScroller;
... ...
}

解决方法

所以唯一的解决方法就是只在convertview中缓存该ChildView的layout,但ChildView 中的数据必须每次都重新获取并加载。其实ListView数据加载及数据缓存是比较复杂的(几个相关的类加起来上完行=。=),所以以后有机会还是要好好研读源码,这样才能更加透彻的理解原理。

查看原文:www.xyczero.com

最新文章

  1. SQL DEFAULT 约束
  2. Linux 下从头再走 GTK+-3.0 (二)
  3. 实时Bug检测工具Bugsnag发布API更新
  4. 获取input标签的所有属性
  5. 16Aspx.com源码2014年7月详细
  6. css 浮动 相对定位 绝对定位区别
  7. window—BAT脚本
  8. Java Code Style
  9. (PMP)第4章-----项目整合管理
  10. 将爬取的数据保存到mysql中
  11. 微信小程序入門學習資料鏈接
  12. OV7670配置和调试小结
  13. Java界面编程—API
  14. Node.js之绝对选择(2018版)
  15. 基于Android的小巫新闻客户端开发系列教程
  16. python获取文件扩展名的方法
  17. 在MS单元测试中引发期望异常
  18. AHOI2018训练日程(3.10~4.12)
  19. 2016级算法第三次上机-G.Winter is coming
  20. docker 中 安装 openssh-server

热门文章

  1. ubuntu 下修改host文件
  2. 差别不在英语水平,而在汉语水平If you do not leave me, we will die together.
  3. SRM 504.5(2-1000pt)
  4. python daemon化你的程序
  5. Rocketmq整体分析
  6. 原生 JavaScript 代码和Jquery实现对比
  7. Coppersmith-Winograd 算法
  8. .Net Framework 4.0安装cmd命令
  9. ios中xib的使用介绍
  10. Aircrack-ng 工具箱