Android性能优化之提升ListView性能的技巧

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

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

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

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

优化前的getView():

@Override
public View getView(int position, View convertView, ViewGroup paramViewGroup) {
        Object current_event = mObjects.get(position);
        ViewHolder holder = null;
        if (convertView == null) {
                holder = new ViewHolder();
                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 = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
        holder.EventPoster.setLayoutParams(imageParams);

        return convertView;
}
复制代码

优化后的getView():

@Override
public View getView(int position, View convertView, ViewGroup paramViewGroup) {
    Object object = mObjects.get(position);
    ViewHolder holder = null;

    if (convertView == null) {
            holder = new ViewHolder();
            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 = new RelativeLayout.LayoutParams(measuredwidth, rowHeight);
            holder.EventPoster.setLayoutParams(imageParams);
            convertView.setTag(holder);
    } else {
            holder = (ViewHolder) convertView.getTag();
    }

    // 咱们直接经过对象的getter方法代替刚才那些逻辑判断,那些逻辑判断放到别的地方去执行了
    holder.ThreeDimension.setVisibility(object.getVisibility());

    return convertView;
}
复制代码

2.GC 垃圾回收器

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

3.加载图片

若是你的ListView中须要显示从网络上下载的图片的话,咱们不要在ListView滑动的时候加载图片,那样会使ListView变得卡顿,因此咱们须要再监听器里面监听ListView的状态,若是滑动的时候,中止加载图片,若是没有滑动,则开始加载图片网络

listView.setOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView listView, int scrollState) {
                    //中止加载图片 
                    if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
                            imageLoader.stopProcessingQueue();
                    } else {
                    //开始加载图片
                            imageLoader.startProcessingQueue();
                    }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                    // TODO Auto-generated method stub

            }
    });
复制代码

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

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

animateCache: ListView默认开启了animateCache,这会消耗大量的内存,所以会频繁调用GC,咱们能够手动将它关闭掉布局

优化前的ListView

<ListView
        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

<ListView
        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的时候,必定要将这几点考虑进去,发挥它的最大的性能。spa