ListView优化

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

  • convertView 复用 + 使用ViewHolder
  • 在adapter中的getView方法中尽量少使用逻辑(逻辑在数据集合处理好)
  • 尽最大可能避免getView中大量创建对象
    • 对象池
  • 滑动的时候不加载图片
  • 将ListView的scrollingCache和animateCache设置为false、
    • scrollingCache将他自己的drawing保存在cache中(保存为一个bitmap),这样下次再显示View的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的,因为它太耗内存了,
  • item的布局层级越少越好
    • 减少不必要的层级 | ConstraintLayout
  • 分页加载

多个viewType复用

private class ChatHeadAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return 50;
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public int getItemViewType(int position) {
            return position % 2;// Type 两种 0和1
        }

        @Override
        public int getViewTypeCount() {
            return 2;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            int viewType = getItemViewType(position);
            LeftViewHolder leftViewHolder = null;
            RightViewHolder rightViewHolder = null;
            if (convertView == null) {
                if (viewType == 0) {// left
                    convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.chat_left_item_text, null);
                    leftViewHolder = new LeftViewHolder();
                    leftViewHolder.leftImageView = (ImageView) convertView.findViewById(R.id.chat_head_iv);
                    convertView.setTag(leftViewHolder);
                } else {
                    convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.chat_right_item_text, null);
                    rightViewHolder = new RightViewHolder();
                    rightViewHolder.rightImageView = (ImageView) convertView.findViewById(R.id.chat_head_iv);
                    convertView.setTag(rightViewHolder);
                }
            } else {
                if (viewType == 0) {// left
                    leftViewHolder = (LeftViewHolder) convertView.getTag();
                } else {
                    rightViewHolder = (RightViewHolder) convertView.getTag();
                }
            }

            if (viewType == 0) {// left
                leftViewHolder.leftImageView.setImageResource(R.drawable.head_temp_left);
            } else {
                rightViewHolder.rightImageView.setImageResource(R.drawable.head_temp_right);
            }

            return convertView;
        }

        class LeftViewHolder {
            ImageView leftImageView;
        }

        class RightViewHolder {
            ImageView rightImageView;
        }
    }

RecyleBin机制分析

保证ListView 加载一页后复用不可见布局, 类位置:android.widget.AbsListView.RecycleBin

RecyclerView优点和缺点

  • 优点:
    • RecyclerView标准化了ViewHolder
    • 提供了一种插拔式的体验,高度的解耦,异常的灵活。
    • 更强大定制功能 ItemAnimator
    • 支持局部刷新
  • 缺点: 在RecyclerView中,没有一个onItemClickListener方法。所以目前在适配器中处理这样的事件比较好。

缓存对比

  • ListView两级缓存,RecyclerBin里面的mActiveViews和mScrapViews, RecyclerView 有四级缓存, RecyclerPool

  • RecyclerView缓存RecyclerView.ViewHolder,抽象可理解为: View + ViewHolder(避免每次createView时调用findViewById) + flag(标识状态);ListView缓存View。

参考文档