android中listview卡顿的终极原因解析

最近在使用Listview时,上下滑动时有些卡顿,后者查阅了资料分析:

通过百度,View在Draw的时候分成两个阶段:measure和layout,在measure阶段时主要就是为了计算两个参数:height和width。而且要注意的是,这是个递归的过程,从顶向下,DecorView开始依次调用自己子元素的measure。计算完成这两个参数后就开始layout,最后再是draw的调用。  
对于ListView,当然每一个Item都会被调用measure方法,而在这个过程中getView和getCount会被调用,而且看用户的需求,可能会有很多次调用。  
  
而为什么会有很多组次调用呢?  
  
问题就在于在layout中的决定ListView或者它的父元素的height和width属性的定义了。fill_parent会好一点,计算方法会比较简单,只要跟父元素的大小相似就行,但是即使是fill_parent,也不能给View当饭吃,还是要计算出来具体的dip,所以measure还是会被调用,只是可能比wrap_content的少一点。至于自适应的它会一直考量它的宽和高,根据内容(也就是它的子Item)计算宽高。可能这个measure过程会反复执行,如果父元素也是wrap_content,这个过程会更加漫长。  
  
所以,解决方法就是尽量避免自适应,除非是万不得已,固定大小或者填充的效果会比较好一些。  
  
于是我们把listview与他父控件的所有高度与宽度都设置为fill_parent,果然getview调用正常了,注意是所有的高度和宽度!  
  
当发现初始化adapter的时候正常调用之后,我们再来尝试滑动listview,发现每出现一个item,当前视图显示的item又调用了一次getview,通过刚哥的这篇帖子,定位到问题在我的getview中使用了// notifyDataSetChanged();   把这行去掉 listview 就已经宣告不再卡顿了!  
  
附带刚哥的listview卡顿终极解决方案原帖:刚哥的Listview卡顿终极解决方案。  


其他卡顿的原因类别:

1..Adapter的getView方法里面convertView没有使用setTag和getTag方式;
2.在getView方法里面ViewHolder初始化后的赋值或者是多个控件的显示状态和背景的显示没有优化好,抑或是里面含有复杂的计算和耗时操作;
3.在getView方法里面 inflate的row 嵌套太深(布局过于复杂)或者是布局里面有大图片或者背景所致;
4.Adapter多余或者不合理的notifySetDataChanged;
5.listview 被多层嵌套,多次的onMessure导致卡顿,如果多层嵌套无法避免,建议把listview的高和宽设置为fill_parent. 如果是代码继承的listview,那么也请你别忘记为你的继承类添加上LayoutPrams,注意高和宽都是fill_parent的;




你可能感兴趣的:(Android,Listview)