ListView优化方案和原理,你都知道了嘛?

1.重用ConvertView

ListView的View回收机制:在可视范围上面或者下面的View加入到回收池中。当在可视范围内的View被移出可视范围内时,其也会被添加到回收池中。以这种方式ListView只需占用非常少的内存几可以存储可视范围内的View和回收池中的View。

参数convertView实际上就是一个可回收的View。当ListView要回收这个View的时候,它的数据就会被清空。因此,当convertView不为null的时候,只需要将数据填充到里面,而不用Inflate一个新的View,这样可以优化性能。因为,Layout的Inflate是消耗资源巨大的代码,因为Infalte操作需要彻底包含整个XML代码树,而且还要实例化相应的View。

public View getView(int position, View convertView, ViewGroup parent) {
		    if (convertView == null) {
		        convertView = mInflater.inflate(R.layout.your_layout, null);
		    }
		    TextView text = (TextView) convertView.findViewById(R.id.text);
		    text.setText("Position " + position);
		    return convertView;
		}

2.使用ViewHolder

ViewHolder就是用来存储那些在你的getView()方法中调用findViewById()方法得到的View。以这种方式,你只需要在第一次创建Item的时候调用findViewById就可以了。

public View getView(int position, View convertView, ViewGroup parent) {
		    ViewHolder holder;
 
		    if (convertView == null) {
		        convertView = mInflater.inflate(R.layout.your_layout, null);
 
		        holder = new ViewHolder();
		        holder.text = (TextView) convertView.findViewById(R.id.text);
 
		        convertView.setTag(holder);
		    } else {
		        holder = convertView.getTag();
		    }
 
		    holder.text.setText("Position " + position);
 
		    return convertView;
		}
 
		private static class ViewHolder {
		    public TextView text;
		}

3.异步加载

加载图片是一个比较耗时的操作,当用户快速滑动列表时,会频繁地 getView ,而 getView 是在主线程中被调用的,如果你在 getView 方法中直接加载 Image 或做其他耗时操作,就会造成滑动比较卡,解决方法是使用异步加载。

  • ListView加载图片乱序问题的解决方法:

    • getView中setTag,可以是图片的url等唯一标识

    • 异步加载后,为ImageView设置图片之前,用findVIewWithTag查找tag是不是为null,不是null才设置图片

其他优化方法:

  • adapter的getView方法中尽可能的减少耗时的操作,getView方法执行的时间只有很短,否则会卡顿。

  • 数据分页分批次加载

  • 快速滑动时不要加载图片,否则会卡顿,如果在滑动时对滑动过的每张图片都要加载,会比较占内存。设置滚动监听,滚动的时候不要加载图片。

  • 尽可能减少ListView的Item的Layout层次(如可以使用RelativeLayout替换LinearLayout,或使用自定的View代替组合嵌套使用的Layout)

  • onClickListener,当ListView的item中有比如button这些子view时,需要对其设置onclickListener,通常的写法是在getView方法中一个个设置,比如

    holder.img.setonClickListener(new onClickListenr)...
    

    但是这种写法每次调用getView时都设置了一个新的onClick事件,都需要new 监听器,效率很低。高效的写法可以直接在ViewHolder中设置一个position,然后viewHolder implements OnClickListenr:

    class  ViewHolder implements OnClickListener{
        int position;
        TextView name;
    
        public void setPosition(int position){
            this.position = position;
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                //XXXX
            }
        }
    }
    
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.list_item, parent, false);
            holder = new ViewHolder();
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.name.setOnClickListener(holder);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        //设置holder
        holder.name.setText(list.get(position).partname);
        //设置position
        holder.setPosition(position);
        return convertView;
    }
    

参考:

https://blog.csdn.net/u014657752/article/details/47379941

https://www.zhihu.com/question/19703384

https://blog.csdn.net/guolin_blog/article/details/45586553

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值