探索ListView复用机制:Android性能提升之道——ListView高效优化技巧解析
Android性能调优-ListView调优
ListView的调优主要涉及以下几方面:
ListView在每次滚动时都会调用getView方法,因此优化getView至关重要。
convertView是刚刚滚动出可视区域的View引用,此时它已经不可见,因此应该被复用以减少View的创建。
LayoutInflater.inflate(resourceId,View)这个方法是通过解析XML文件的方式从XML生成一个View对象的,如果有成千上万个View都要去解析XML生成View,会非常消耗性能。
ViewHolder
findViewById这个方法是从ViewGroup的子View中循环遍历查找id与给出的ID相同的子View,相对耗时,
图片加载顺序,应为,内存--本地--网络
主要介绍缓存到内存中的方法,
据传以前使用HashMap<String,SoftReference\>的方法缓存,不过现在大多使用LruCache,
从网络加载图片或者本地加载图片都比较耗时,加上Android16ms的刷新UI频率,会造成卡顿
从内存获取速度相对较快,以上只是放入内存的方法,当然压缩等操作就没有写,只是简单介绍存入内存的原理
很多情况下ListView需要加载显示网络图片,我们尽量不要在ListView滑动时加载网络图片,那样会使ListView变得卡顿,所以我们要监听ListView的状态,如果ListView滑动(SCROLL_STATE_TOUCH_SCROLL)或者猛滑(SCROLL_STATE_FLING)时,停止加载图片,否则加载图片
从用户的角度讲,快速滑动时,用户不需要看到当前内容
有时候除了onItemClickListener之外,我们还会用到Item上其他位置的点击事件
一般情况下我们是在getView方法中,一个一个设置,就像这样每个都设置了一个新的OnClickListener对象,不太好
直接在ViewHolder中设置一个position,然后viewHolder implements OnClickListener,然后再getView中设置的时候设置自己就行了
总之,宗旨就是少在getView里面new对象,做耗时操作
ListView卡顿的难题
在使用ListView组件时,我们发现当列表项超过50个时,组件变得异常卡顿,甚至在性能调优中期待的20fps也未能实现。对于这个问题,我们开始探究原因和解决方法。
查阅资料后,得知ListView采用懒加载机制,仅绘制屏幕范围内的item,而屏幕外的item则会被销毁。因此,即便列表项数量庞大,也不应出现卡顿情况,因为它仅负责加载屏幕上几个item。然而,在实践中,我们遇到的卡顿现象并非如此。
问题在于,当我们使用shrinkWrap: true和physics: const NeverScrollableScrollPhysics()时,ListView组件不再采用懒加载机制。相反,它会加载所有item,从而生成一个超长列表,以便外层的SingleChildScrollView组件能够进行滚动。这导致了严重的卡顿。
找到问题所在后,我们开始思考解决方案。去除shrinkWrap和NeverScrollableScrollPhysics,ListView组件可以正常加载和滚动。然而,这样做又会与外层的SingleChildScrollView组件产生冲突,尤其是需要EasyRefresh组件实现刷新和上拉加载更多功能时。因此,我们不得不自行实现这一功能。
为了解决刷新和上拉加载更多功能,我们设计了一个自定义的RefreshLoad类。这个类结合了EasyRefresh的刷新功能以及监听滚动控制器的加载更多功能,使得ListView组件能够在保持流畅性能的同时,满足刷新和加载更多需求。
通过将自定义的RefreshLoad类应用到实际项目中,我们成功地实现了ListView组件的优化,解决了卡顿问题。这一解决方案不仅解决了性能问题,还满足了项目中对刷新和加载更多功能的需求。最终,我们获得了一个高效且功能丰富的ListView组件,提升了用户体验。
共有 0 条评论