RecyclerView Glide加载图片错乱

问题描述:

当快速滑动时,由于图片是通过网络异步加载的,导致在图片下载完成之后,之前设置的加载对象ImageView所在的ViewHolder 已被回收再利用到其他position的item了。最终就会出现图片加载错乱的问题。

而且由于快速滑动,并不停的加载切换图片,还会出现卡顿的现象。

然后为了解决错乱的问题,当使用Glide加载图片时,给ImageView设置tag,却:

You must not call setTag() on a view Glide is targeting

Glide 报错。。。

分析

Glide 加载图片时,为了避免一定程度上的错乱问题,以request作为tag,为每个ImageView设置了tag。

    @Nullable
    public Request getRequest() {
        Object tag = this.getTag();
        Request request = null;
        if (tag != null) {
            if (!(tag instanceof Request)) {
                throw new IllegalArgumentException("You must not call setTag() on a view Glide is targeting");
            }

            request = (Request)tag;
        }

        return request;
    }

所以当我们直接调用 imageView.setTag() 时,然后再调用Glide时会报错。

那么给ImageView设置tag,可以通过 setTag(key,object) 来设置


    /**
     * Sets a tag associated with this view and a key. A tag can be used
     * to mark a view in its hierarchy and does not have to be unique within
     * the hierarchy. Tags can also be used to store data within a view
     * without resorting to another data structure.
     *
     * The specified key should be an id declared in the resources of the
     * application to ensure it is unique (see the ID resource type).
     * Keys identified as belonging to
     * the Android framework or not associated with any package will cause
     * an {@link IllegalArgumentException} to be thrown.
     *
     * @param key The key identifying the tag
     * @param tag An Object to tag the view with
     *
     * @throws IllegalArgumentException If they specified key is not valid
     *
     * @see #setTag(Object)
     * @see #getTag(int)
     */
    public void setTag(int key, final Object tag) {
        // If the package id is 0x00 or 0x01, it's either an undefined package
        // or a framework id
        if ((key >>> 24) < 2) {
            throw new IllegalArgumentException("The key must be an application-specific "
                    + "resource id.");
        }

        setKeyedTag(key, tag);
    }

注释告诉我们,这个key,必须是在xml resource中创建的资源id。

另外当我们快速滑动时,可以通过监听滑动状态,当处于滑动状态时,我们不需要架加载图片。因为用户此时并不关心图片是否加载出来,反而因为加载图片会带来卡顿问题,这就得不偿失了。判断只有处于滑动空闲状态时,在bindViewHolder中才去加载图片。

代码

String url = itemData.url

if(imageView.getTag(R.id.image_url) != url){
    //当前ImageView绑定的tag与数据源中需要加载的 url不一致,
    //即:发生了复用情况。此时需要将可能存在的之前的图片用占位图取缔掉。
    imageView.setImageDrawable(mDefaultDrawable)
}
//只有不处于滑动状态 而且 允许通过网络加载图片时
if(mIsScrollIdle && mCanLoadFromNet){
    //再之后重新绑定 tag 并加载图片    
    imageView.setTag(R.id.image_url,url)
    Glide.with(ctx).load(url).into(imageView)
}


    

你可能感兴趣的:(RecyclerView Glide加载图片错乱)