总结:listView等的优化和图片错位问题

ListView,RecyclerView 用过很多,写起来也没什么难度,但最近面试时被问及这个问题,发觉答的都不全面,现总结下最全面的优化方案如下:

  1. ContentVeiw的复用。在RecyclerView中强制必须复用。listView中就要自己实现,listview的复用机制就是条目很多的时候,只会创建满一屏的条目,当滑动的时候不会再去创建新的view,而是复用已经滑出屏幕的view,对于view有一个缓存。
public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            view = inflater.inflate(R.layout.item, null);
        }
        return convertView;
    }
  1. ViewHolder 的使用。RecyclerView自带了ViewHolder 。ListView 需要我们自己实现。ViewHolder作用主要是减少findViewById的操纵。

  2. 分页加载。如果数据较多不用全部展示在listView中,可以分页加载。每次往数据源中添加一页的数据,这样如果用户一直刷一直加载,数据源中数据也会越来越多,这个时候页可以保持一页的数据源,每次下拉或上拉就清空数据源在放入上一页或下一页的数据,数据源始终保持一页或几页的数据。

  3. 减少item布局层次,可以用ConstraintLayout 约束布局使布局只有一个层次,使用merge和include 绘制布局。

  4. 滑动时停止加载图片,停止滑动时再加载图片。例如使用Glide加载图片时可以给listview或recyclerView设置滑动监听

listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState) {
                    case SCROLL_STATE_IDLE: //停止滑动
                        Glide.with(mContext).resumeRequests();
                        break;
                    case SCROLL_STATE_FLING://惯性滑动
                    case SCROLL_STATE_TOUCH_SCROLL://手指触摸滑动

                        Glide.with(mContext).pauseRequests();
                        break;
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });

但是这种方式在滑动视觉效果上有点突兀,因为滑动的时候界面不加载,一停止就加载出来了,有点闪动的感觉,这个看取舍了。

错位问题

ListView 和RecyclerView中加载图片时会出现图片错位的问题。出现该问题的条件必须是 复用+异步,缺少一个都不会造成错乱。假设一屏上有7个条目,向上滑动,条目1会复用到条目8的位置。虽然位置不一样了,但是再内存中是同一个指向,还是同一个view。再getView方法中会先刷上位置1的数据,然后再刷上位置8的数据,因为是异布,如果网速再不好,那么会出现这种可能,条目复用到8的位置时刷的数据才加载出图片,如果1处的数据先加载,8的后加载,就出现条目8先出现位置1的图片后又出现条目8的图片,如果8处的图片先加载,就出现条目8先出现位置8的图片,后又出现位置1处的图片。

解决办法,在getView刷数据的时候给View设置图片url的tag,异步加载图片完成后去取tag,判断是否是加载的图片的url。这样在每次刷数据的时候都会给view设置当前加载图片的url,即使复用后异步加载了不属于该位置的图片也不会设置了。

 public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item, null);
        }
        final ImageView imageView = (ImageView) convertView.findViewById(R.id.img);
        final String pic_url = (String) list.get(position);

        imageView.setTag(pic_url);
        Glide.with(mContext).load(pic_url).into(new SimpleTarget<GlideDrawable>() {
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {

                String urlTag = (String) imageView.getTag();
                if (!TextUtils.isEmpty(urlTag) && urlTag.equals(pic_url)) {
                    imageView.setImageDrawable(resource);
                }
            }
        });

        return convertView;
    }
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值