1

提高ListView性能的技巧

 2 years ago
source link: http://www.androidchina.net/3189.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

  • 在adapter中的getView方法中尽量少使用逻辑
  • 尽最大可能避免GC
  • 滑动的时候不加载图片
  • 将ListView的scrollingCache和animateCache设置为false
  • item的布局层级越烧越好
  • 使用ViewHolder

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

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

优化前的getView():

<br />@Override<br />public View getView(int position, View convertView, ViewGroup paramViewGroup) {<br /><%%KEEPWHITESPACE%%>        Object current_event = mObjects.get(position);<br /><%%KEEPWHITESPACE%%>        ViewHolder holder = null;<br /><%%KEEPWHITESPACE%%>        if (convertView == null) {<br /><%%KEEPWHITESPACE%%>                holder = new ViewHolder();<br /><%%KEEPWHITESPACE%%>                convertView = inflater.inflate(R.layout.row_event, null);<br /><%%KEEPWHITESPACE%%>                holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);<br /><%%KEEPWHITESPACE%%>                holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);<br /><%%KEEPWHITESPACE%%>                convertView.setTag(holder);<br /><br /><%%KEEPWHITESPACE%%>        } else {<br /><%%KEEPWHITESPACE%%>                holder = (ViewHolder) convertView.getTag();<br /><%%KEEPWHITESPACE%%>        }<br /><br /><%%KEEPWHITESPACE%%>       //在这里进行逻辑判断,这是有问题的<br /><%%KEEPWHITESPACE%%>        if (doesSomeComplexChecking()) {<br /><%%KEEPWHITESPACE%%>                holder.ThreeDimention.setVisibility(View.VISIBLE);<br /><%%KEEPWHITESPACE%%>        } else {<br /><%%KEEPWHITESPACE%%>                holder.ThreeDimention.setVisibility(View.GONE);<br /><%%KEEPWHITESPACE%%>        }<br /><br /><%%KEEPWHITESPACE%%>        // 这是设置image的参数,每次getView方法执行时都会执行这段代码,这显然是有问题的<br /><%%KEEPWHITESPACE%%>        RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);<br /><%%KEEPWHITESPACE%%>        holder.EventPoster.setLayoutParams(imageParams);<br /><br /><%%KEEPWHITESPACE%%>        return convertView;<br />}<br />

优化后的getView():

<br />@Override<br />public View getView(int position, View convertView, ViewGroup paramViewGroup) {<br /><%%KEEPWHITESPACE%%>    Object object = mObjects.get(position);<br /><%%KEEPWHITESPACE%%>    ViewHolder holder = null;<br /><br /><%%KEEPWHITESPACE%%>    if (convertView == null) {<br /><%%KEEPWHITESPACE%%>            holder = new ViewHolder();<br /><%%KEEPWHITESPACE%%>            convertView = inflater.inflate(R.layout.row_event, null);<br /><%%KEEPWHITESPACE%%>            holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim);<br /><%%KEEPWHITESPACE%%>            holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster);<br /><%%KEEPWHITESPACE%%>            //设置参数提到这里,只有第一次的时候会执行,之后会复用<br /><%%KEEPWHITESPACE%%>            RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);<br /><%%KEEPWHITESPACE%%>            holder.EventPoster.setLayoutParams(imageParams);<br /><%%KEEPWHITESPACE%%>            convertView.setTag(holder);<br /><%%KEEPWHITESPACE%%>    } else {<br /><%%KEEPWHITESPACE%%>            holder = (ViewHolder) convertView.getTag();<br /><%%KEEPWHITESPACE%%>    }<br /><br /><%%KEEPWHITESPACE%%>    // 我们直接通过对象的getter方法代替刚才那些逻辑判断,那些逻辑判断放到别的地方去执行了<br /><%%KEEPWHITESPACE%%>    holder.ThreeDimension.setVisibility(object.getVisibility());<br /><br /><%%KEEPWHITESPACE%%>    return convertView;<br />}<br />

2.GC 垃圾回收器

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

3.加载图片

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

<br />listView.setOnScrollListener(new OnScrollListener() {<br /><br /><%%KEEPWHITESPACE%%>            @Override<br /><%%KEEPWHITESPACE%%>            public void onScrollStateChanged(AbsListView listView, int scrollState) {<br /><%%KEEPWHITESPACE%%>                    //停止加载图片<br /><%%KEEPWHITESPACE%%>                    if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {<br /><%%KEEPWHITESPACE%%>                            imageLoader.stopProcessingQueue();<br /><%%KEEPWHITESPACE%%>                    } else {<br /><%%KEEPWHITESPACE%%>                    //开始加载图片<br /><%%KEEPWHITESPACE%%>                            imageLoader.startProcessingQueue();<br /><%%KEEPWHITESPACE%%>                    }<br /><%%KEEPWHITESPACE%%>            }<br /><br /><%%KEEPWHITESPACE%%>            @Override<br /><%%KEEPWHITESPACE%%>            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {<br /><%%KEEPWHITESPACE%%>                    // TODO Auto-generated method stub<br /><br /><%%KEEPWHITESPACE%%>            }<br /><%%KEEPWHITESPACE%%>    });<br />

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

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

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

优化前的ListView

<br /><ListView<br /><%%KEEPWHITESPACE%%>        android:id="@android:id/list"<br /><%%KEEPWHITESPACE%%>        android:layout_width="match_parent"<br /><%%KEEPWHITESPACE%%>        android:layout_height="wrap_content"<br /><%%KEEPWHITESPACE%%>        android:cacheColorHint="#00000000"<br /><%%KEEPWHITESPACE%%>        android:divider="@color/list_background_color"<br /><%%KEEPWHITESPACE%%>        android:dividerHeight="0dp"<br /><%%KEEPWHITESPACE%%>        android:listSelector="#00000000"<br /><%%KEEPWHITESPACE%%>        android:smoothScrollbar="true"<br /><%%KEEPWHITESPACE%%>        android:visibility="gone" /><br /><br />

优化后的ListView

<br /><ListView<br /><%%KEEPWHITESPACE%%>        android:id="@android:id/list"<br /><%%KEEPWHITESPACE%%>        android:layout_width="match_parent"<br /><%%KEEPWHITESPACE%%>        android:layout_height="wrap_content"<br /><%%KEEPWHITESPACE%%>        android:divider="@color/list_background_color"<br /><%%KEEPWHITESPACE%%>        android:dividerHeight="0dp"<br /><%%KEEPWHITESPACE%%>        android:listSelector="#00000000"<br /><%%KEEPWHITESPACE%%>        android:scrollingCache="false"<br /><%%KEEPWHITESPACE%%>        android:animationCache="false"<br /><%%KEEPWHITESPACE%%>        android:smoothScrollbar="true"<br /><%%KEEPWHITESPACE%%>        android:visibility="gone" /><br />

5.减少item的布局的深度

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

6.使用ViewHolder

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

ListView的优化我们已经讲完了,如果在你的项目中,这些基本优化你还没有做到的话,那么你的ListView是有问题的,还有很大的提升潜力,以后再使用ListView的时候,一定要将这几点考虑进去,发挥它的最大的性能。

转载请注明:Android开发中文站 » 提高ListView性能的技巧


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK