服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - 浅谈Android开发中ListView控件性能的一些优化方法

浅谈Android开发中ListView控件性能的一些优化方法

2021-05-12 17:18左老怪 Android

这篇文章主要介绍了Android开发中ListView控件性能的一些优化方法,需要的朋友可以参考下

ListView优化一直是一个老生常谈的问题,不管是面试还是平常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来看看如何最大化的优化ListView的性能。

1.在adapter中的getView方法中尽量少使用逻辑

2.尽最大可能避免GC

3.滑动的时候不加载图片

4.将ListView的scrollingCache和animateCache设置为false

5.item的布局层级越少越好

6.使用ViewHolder

下面就具体来看一些

1.在adapter中的getView方法中尽量少使用逻辑

不要在你的getView()中写过多的逻辑代码,我们可以将这些代码放在别的地方,例如:

优化前的getView():

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Override
 
public View getView(intposition, View convertView, ViewGroup paramViewGroup) {
 
Object current_event = mObjects.get(position);
 
ViewHolder holder =null;if(convertView ==null) {
 
holder =newViewHolder();
 
convertView = inflater.inflate(R.layout.row_event,null);
 
holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
 
holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
 
convertView.setTag(holder);
 
}else{
 
holder = (ViewHolder) convertView.getTag();
 
}
 
//在这里进行逻辑判断,这是有问题的
 
if(doesSomeComplexChecking()) {
 
holder.ThreeDimention.setVisibility(View.VISIBLE);
 
}else{
 
holder.ThreeDimention.setVisibility(View.GONE);
 
}
 
// 这是设置image的参数,每次getView方法执行时都会执行这段代码,这显然是有问题的
 
RelativeLayout.LayoutParams imageParams =newRelativeLayout.LayoutParams(measuredwidth, rowHeight);
 
holder.EventPoster.setLayoutParams(imageParams);
 
returnconvertView;
 
}

优化后的getView():

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Override
 
public View  getView(intposition, View convertView, ViewGroup paramViewGroup) {
 
Object object = mObjects.get(position);
 
ViewHolder holder =null;if(convertView ==null) {
 
holder =newViewHolder();
 
convertView = inflater.inflate(R.layout.row_event,null);
 
holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);
 
holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);
 
//设置参数提到这里,只有第一次的时候会执行,之后会复用
 
RelativeLayout.LayoutParams imageParams =newRelativeLayout.LayoutParams(measuredwidth, rowHeight);
 
holder.EventPoster.setLayoutParams(imageParams);
 
convertView.setTag(holder);
 
}else{
 
holder = (ViewHolder) convertView.getTag();
 
}// 我们直接通过对象的getter方法代替刚才那些逻辑判断,那些逻辑判断放到别的地方去执行了holder.ThreeDimension.setVisibility(object.getVisibility());returnconvertView;
 
}

2.GC 垃圾回收器

当你创建了大量的对象的时候,GC就会频繁的执行,所以在getView()方法中不要创建很多的对象,最好的优化是,不要在ViewHolder以外创建任何对象,如果你的你的log里面发现“GC has freed some memory”频繁出现的话,那你的程序肯定有问题了。你可以检查一下:

a) item布局的层级是否太深

b) getView()方法中是否有大量对象存在

c) ListView的布局属性

3.加载图片

如果你的ListView中需要显示从网络上下载的图片的话,我们不要在ListView滑动的时候加载图片,那样会使ListView变得卡顿,所以我们需要再监听器里面监听ListView的状态,如果滑动的时候,停止加载图片,如果没有滑动,则开始加载图片

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
listView.setOnScrollListener(newOnScrollListener() {
 
@Override
 
public void onScrollStateChanged(AbsListView listView,intscrollState) {
 
//停止加载图片
 
if(scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
 
imageLoader.stopProcessingQueue();
 
}else{
 
//开始加载图片
 
imageLoader.startProcessingQueue();
 
}
 
}
 
@Override
 
public void onScroll(AbsListView view,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount) {
 
// TODO Auto-generated method stub}
 
});

4.将ListView的scrollingCache和animateCache设置为false

scrollingCache:scrollingCache本质上是drawing cache,你可以让一个View将他自己的drawing保存在cache中(保存为一个bitmap),这样下次再显示View的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的,因为它太耗内存了,但是它确实比重画来的更加平滑。而在ListView中,scrollingCache是默认开启的,我们可以手动将它关闭。

animateCache:ListView默认开启了animateCache,这会消耗大量的内存,因此会频繁调用GC,我们可以手动将它关闭掉

优化前的ListView

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<android:id="@android:id/list"
 
android:layout_width="match_parent"
 
android:layout_height="wrap_content"
 
android:cacheColorHint="#00000000"
 
android:divider="@color/list_background_color"
 
android:dividerHeight="0dp"
 
android:listSelector="#00000000"
 
android:smoothScrollbar="true"
 
android:visibility="gone"/>

优化后的ListView

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<android:id="@android:id/list"
 
android:layout_width="match_parent"
 
android:layout_height="wrap_content"
 
android:divider="@color/list_background_color"
 
android:dividerHeight="0dp"
 
android:listSelector="#00000000"
 
android:scrollingCache="false"
 
android:animationCache="false"
 
android:smoothScrollbar="true"
 
android:visibility="gone"/>

5.减少item的布局的深度

我们应该尽量减少item布局深度,因为当滑动ListView的时候,这回直接导致测量与绘制,因此会浪费大量的时间,所以我们应该将一些不必要的布局嵌套关系去掉。减少item布局深度

6.使用ViewHolder

这个大家应该非常熟悉了,但是不要小看这个ViewHolder,它可以大大提高我们ListView的性能

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的;  以往我一般都是将listview的高度设置成fill_parent,而这次我是设为wrap_content,这样做的问题在于,ListView没有取到实际的高度,他还要根据计算才能确定,而每一次计算应该会触发listview的渲染,所以就会出现getview的调用次数跟正常情况相比多了好几倍。所以在一般情况下,我建议把listiview在布局文件中的高度总是设置为:fill_parent(或者match_parent),这不仅仅是getview的调用次数问题,还涉及到布局的效率。

延伸 · 阅读

精彩推荐
  • AndroidAndroid CardView+ViewPager实现ViewPager翻页动画的方法

    Android CardView+ViewPager实现ViewPager翻页动画的方法

    本篇文章主要介绍了Android CardView+ViewPager实现ViewPager翻页动画的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Abby代黎明9602022-03-02
  • AndroidAndroid实现Service获取当前位置(GPS+基站)的方法

    Android实现Service获取当前位置(GPS+基站)的方法

    这篇文章主要介绍了Android实现Service获取当前位置(GPS+基站)的方法,较为详细的分析了Service基于GPS位置的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    Ruthless8342021-03-31
  • Android汇总Android视频录制中常见问题

    汇总Android视频录制中常见问题

    这篇文章主要汇总了Android视频录制中常见问题,帮助大家更好地解决Android视频录制中常见的问题,需要的朋友可以参考下...

    yh_thu5192021-04-28
  • AndroidAndroid程序设计之AIDL实例详解

    Android程序设计之AIDL实例详解

    这篇文章主要介绍了Android程序设计的AIDL,以一个完整实例的形式较为详细的讲述了AIDL的原理及实现方法,需要的朋友可以参考下...

    Android开发网4642021-03-09
  • AndroidAndroid界面效果UI开发资料汇总(附资料包)

    Android界面效果UI开发资料汇总(附资料包)

    android ui界面设计,友好的界面会提高用户体验度;同时也增强了android ui界面设计的难度,本文提供了一些常用开发资料(有下载哦)感兴趣的朋友可以了解下...

    Android开发网4672021-01-03
  • AndroidAndroid编程解析XML方法详解(SAX,DOM与PULL)

    Android编程解析XML方法详解(SAX,DOM与PULL)

    这篇文章主要介绍了Android编程解析XML方法,结合实例形式详细分析了Android解析XML文件的常用方法与相关实现技巧,需要的朋友可以参考下...

    liuhe68810052021-05-03
  • AndroidAndroid实现固定屏幕显示的方法

    Android实现固定屏幕显示的方法

    这篇文章主要介绍了Android实现固定屏幕显示的方法,实例分析了Android屏幕固定显示所涉及的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    鉴客6192021-03-27
  • AndroidAndroid中AsyncTask详细介绍

    Android中AsyncTask详细介绍

    这篇文章主要介绍了Android中AsyncTask详细介绍,AsyncTask是一个很常用的API,尤其异步处理数据并将数据应用到视图的操作场合,需要的朋友可以参考下...

    Android开发网7452021-03-11