最新消息:欢迎访问Android开发中文站!商务联系微信:loading_in

提高ListView性能的技巧

开发进阶 AndroidChina 3231浏览 0评论

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 />&lt;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" /&gt;<br /><br />

优化后的ListView

<br />&lt;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" /&gt;<br />

5.减少item的布局的深度

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

6.使用ViewHolder

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

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

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

您必须 登录 才能发表评论!