ListView 优化
最近在做项目过程中频繁使用列表,今天抽空总结下过程中遇到的问题,下面会有具体对应的解决办法;
- 1.listView 外套一层ScrollView 的问题,就是listView 只显示一行或者两行, 我发现这个问题在 RecycleView 上也存在, 在RecycleView外套一层 ScrollView也会出现只显示一行的问题,滑动只能在 一行的高度内滑动。这问题下面有具体解决方案,说下我是怎么解决的吧,因为我要实现的是9宫格的图片展示,本来是用的RecycleView 来实现的,出现了这个问题,我就尝试把recyclerView 换成了GridView 了,因为GridView 本身就支持多行展示,发现就没有这个问题了,套了ScrollView 也正常展示;
- 2.也是listView 在嵌套ScrollView 中的问题,在某款三星手机上,这个手机的虚拟按键,可以锁定和解锁定, 发现在切换锁定和解锁定中,会导致原来的多行的图片变成单行, 在别的手机上就没有这个问题, 这个奇怪的现象,最终还是以GridView 替换掉listView 解决的。
- 3.listView 添加 headerView的问题, 需要注意的是 添加进去的 HeaderView 就占据了第0位,所以在使用的 onItemClick 的时候,需要-1, addfooterView的时候可以用 view.getFooterViewsCount() 是否等于0来判断,避免多次添加。
- 4.由于listView 会复用viewHolder ,所以我们在getView 中 显示隐藏的设置一定要配套使用,if里有显示,在else 中就要 隐藏。
优化步骤:
使用 RecycleView 代替listview
- 1.重用ConvertView;
- 2.使用View Holder模式;
- 3.使用异步线程加载图片(一般都是直接使用图片库加载,如Glide, Picasso);
建议:
- 1.在adapter的getView方法中尽可能的减少逻辑判断,特别是耗时的判断;
- 2.避免GC
- 3.在快速滑动时不要加载图片;
- 4.将ListView的scrollingCache和animateCache这两个属性设置为false(默认是true);
- 5.尽可能减少List Item的Layout层次(如可以使用RelativeLayout替换LinearLayout,或使用自定的View代替组合嵌套使用的Layout)
ListView 嵌套 ScrollView
Listview不能显示正常的条目,只显示一条或二条
这是因为:由于listView在scrollView中无法正确计算它的大小, 故只显示一行。
解决方案:
1. 方法一:重写ListView, 覆盖onMeasure()方法
1 | WrapperListView.java: |
2.方法二:动态设置listview的高度,不需要重写ListView
只需要在setAdapter之后调用如下方法即可:
1 | public void setListViewHeightBasedOnChildren(ListView listView) { |
这时最好给ListView之外嵌套一层LinearLayout,不然有时候这种方法会失效
3.方法三:在xml文件中,直接将Listview的高度写死
可以确定的是:这种方式可以改变ListView的高度,但是,还有一个严重的问题就是listview的数据是可变动的,除非你能正确的写出listview的高度,否则这种方式就是个鸡肋。
4. addHeadView()
如果只有数据 layout 完全没有必要嵌套 ScrollView 的.之说以需要嵌套,很多是在listView 头部或者底部多了一部分Layout ,这个时候可以尝试 listView 的 addHeadView() 尝试解决
在一次显示ListView的界面时,getView会被执行几次?
比如有5组数据要填充到listView。listView会先调用onMeasure,此时会调用5次getView。然后才调用onLayout,此时又会调用5次getView,这样就重复了。所以导致多次调用getView方法
的确调用了三遍
解决办法:
ListView 的高度 从 wrap_content 改成 match_patent 或者一个固定值,就能减少getview 调用次数
或者重写 listView 的onMasure onLayout 方法 赋值 一个变量 检测 是测量还是layout 测量时不加载自己写的那段逻辑
listview失去焦点怎么处理?
在listview子布局里面写,可以解决焦点失去的问题
android:descendantFocusability=”blocksDescendants”
ListView 优化
1.首先,虽然大家都知道,还是提一下,利用好 convertView 来重用 View,切忌每次 getView() 都新建。ListView 的核心原理就是重用 View。ListView 中有一个回收器,Item 滑出界面的时候 View 会回收到这里,需要显示新的 Item 的时候,就尽量重用回收器里面的 View。
2.利用好 View Type,例如你的 ListView 中有几个类型的 Item,需要给每个类型创建不同的 View,这样有利于 ListView 的回收,当然类型不能太多
- 3.尽量让 ItemView 的 Layout 层次结构简单,这是所有 Layout 都必须遵循的
- 4.善用自定义 View,自定义 View 可以有效的减小 Layout 的层级,而且对绘制过程可以很好的控制;
- 5.尽量能保证 Adapter 的 hasStableIds() 返回 true,这样在 notifyDataSetChanged() 的时候,如果 id 不变,ListView 将不会重新绘制这个 View,达到优化的目的;
- 6.每个 Item 不能太高,特别是不要超过屏幕的高度,可以参考 Facebook 的优化方法,把特别复杂的 Item 分解成若干小的 Item,
- 7.为了保证 ListView 滑动的流畅性,getView() 中要做尽量少的事情,不要有耗时的操作。特别是滑动的时候不要加载图片,停下来再加载,这个库可以帮助你 Glide:https://github.com/bumptech/glide
- 8.使用 RecycleView 代替。 ListView 每次更新数据都要 notifyDataSetChanged(),有些太暴力了。RecycleView 在性能和可定制性上都有很大的改善,推荐使用。