美文网首页
记一次recyclerview item删除图片异常显示bug

记一次recyclerview item删除图片异常显示bug

作者: Sunny君907 | 来源:发表于2019-07-12 18:19 被阅读0次

    之前recyclerview中有imageview,会通过glide对其设置图片,但是有的可能没有图片,就必须显示默认图片,在imageview中设置了默认resId资源,但是在进行删除部分item操作后,显示默认图片的会变空白,因此在onBindViewHolder中添加设置,没有图片时添加一个默认图片,用的是holder.headImg.setBackground的方法,然后删除图片的item后就正常了(全部默认图片情况下)...
    就这么结束了吗,但是但是,一开始是glide图片的item,默认图片item,删除glide图片的item,结果,默认图片竟然变成了被删除的item的图片,一开始很自然的想当然应该是recyclerview的item复用问题,但是每次onBindViewHolder都会设置啊,然后单选全选,列表中又出现了很诡异的事情,选中带glide图片item,再选默认图片的item,默认图片全被替换成了glide图片,神马情况...
    是imageview加tag吗?glide加了tag报错啊...我还尝试了(微笑脸,try catch让我勇往直前),然后还尝试将imageview资源用setImageDrawable(null)设置后再setBackground,然而现象朝着更加诡异的方法发展,单选glide图片变成了默认或者默认图片变glide加载图片 ...
    最后的最后,将setBackground改为setImageDrawable/setImageResource,然后问题解决了...改完感觉自己...
    心好累啊,使用imageview的setImageDrawable直接绘制多好,简单粗暴;view的setBackground各种判断,最终可能还没法重绘制,导致图片错位复用,平时还是得多看源码。

    ×××××
    上次修改后,由发现进入的时候,某些默认图片会显示设置图片,明明显示的并没有资源,什么鬼...我怀疑和glide有关系,pic有资源用glide给imageView加载,没有的话直接用imageview设置本地res文件,然后将pic为空时,也用glide来设置,Glide.with(context).load(R.drawable.ic_person).into(holder.headImg);显示正常,之前出现的异常现象也ok。

    ImageView的setImageDrawable,setImageResource方法

    public void setImageDrawable(@Nullable Drawable drawable) {
            if (mDrawable != drawable) {
                mResource = 0;
                mUri = null;
    
                final int oldWidth = mDrawableWidth;
                final int oldHeight = mDrawableHeight;
    
                updateDrawable(drawable);
    
                if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
                    requestLayout();
                }
                invalidate();
            }
        }
    
        /**
         * Sets a drawable as the content of this ImageView.
         * <p class="note">This does Bitmap reading and decoding on the UI
         * thread, which can cause a latency hiccup.  If that's a concern,
         * consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)} or
         * {@link #setImageBitmap(android.graphics.Bitmap)} and
         * {@link android.graphics.BitmapFactory} instead.</p>
         *
         * @param resId the resource identifier of the drawable
         *
         * @attr ref android.R.styleable#ImageView_src
         */
        @android.view.RemotableViewMethod(asyncImpl="setImageResourceAsync")
        public void setImageResource(@DrawableRes int resId) {
            // The resource configuration may have changed, so we should always
            // try to load the resource even if the resId hasn't changed.
            final int oldWidth = mDrawableWidth;
            final int oldHeight = mDrawableHeight;
    
            updateDrawable(null);
            mResource = resId;
            mUri = null;
    
            resolveUri();
    
            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
                requestLayout();
            }
            invalidate();
        }
    

    View的setBackground

    /**
         * Set the background to a given resource. The resource should refer to
         * a Drawable object or 0 to remove the background.
         * @param resid The identifier of the resource.
         *
         * @attr ref android.R.styleable#View_background
         */
     @RemotableViewMethod
        public void setBackgroundResource(@DrawableRes int resid) {
            if (resid != 0 && resid == mBackgroundResource) {
                return;
            }
    
            Drawable d = null;
            if (resid != 0) {
                d = mContext.getDrawable(resid);
            }
            setBackground(d);
    
            mBackgroundResource = resid;
        }
    
     /**
         * Set the background to a given Drawable, or remove the background. If the
         * background has padding, this View's padding is set to the background's
         * padding. However, when a background is removed, this View's padding isn't
         * touched. If setting the padding is desired, please use
         * {@link #setPadding(int, int, int, int)}.
         *
         * @param background The Drawable to use as the background, or null to remove the
         *        background
         */
        public void setBackground(Drawable background) {
            //noinspection deprecation
            setBackgroundDrawable(background);
        }
    
        /**
         * @deprecated use {@link #setBackground(Drawable)} instead
         */
        @Deprecated
        public void setBackgroundDrawable(Drawable background) {
            computeOpaqueFlags();
    
            if (background == mBackground) {
                return;
            }
    
            boolean requestLayout = false;
    
            mBackgroundResource = 0;
    
            /*
             * Regardless of whether we're setting a new background or not, we want
             * to clear the previous drawable. setVisible first while we still have the callback set.
             */
            if (mBackground != null) {
                if (isAttachedToWindow()) {
                    mBackground.setVisible(false, false);
                }
                mBackground.setCallback(null);
                unscheduleDrawable(mBackground);
            }
    
            if (background != null) {
                Rect padding = sThreadLocal.get();
                if (padding == null) {
                    padding = new Rect();
                    sThreadLocal.set(padding);
                }
                resetResolvedDrawablesInternal();
                background.setLayoutDirection(getLayoutDirection());
                if (background.getPadding(padding)) {
                    resetResolvedPaddingInternal();
                    switch (background.getLayoutDirection()) {
                        case LAYOUT_DIRECTION_RTL:
                            mUserPaddingLeftInitial = padding.right;
                            mUserPaddingRightInitial = padding.left;
                            internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
                            break;
                        case LAYOUT_DIRECTION_LTR:
                        default:
                            mUserPaddingLeftInitial = padding.left;
                            mUserPaddingRightInitial = padding.right;
                            internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
                    }
                    mLeftPaddingDefined = false;
                    mRightPaddingDefined = false;
                }
    
                // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
                // if it has a different minimum size, we should layout again
                if (mBackground == null
                        || mBackground.getMinimumHeight() != background.getMinimumHeight()
                        || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
                    requestLayout = true;
                }
    
                // Set mBackground before we set this as the callback and start making other
                // background drawable state change calls. In particular, the setVisible call below
                // can result in drawables attempting to start animations or otherwise invalidate,
                // which requires the view set as the callback (us) to recognize the drawable as
                // belonging to it as per verifyDrawable.
                mBackground = background;
                if (background.isStateful()) {
                    background.setState(getDrawableState());
                }
                if (isAttachedToWindow()) {
                    background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
                }
    
                applyBackgroundTint();
    
                // Set callback last, since the view may still be initializing.
                background.setCallback(this);
    
                if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
                    requestLayout = true;
                }
            } else {
                /* Remove the background */
                mBackground = null;
                if ((mViewFlags & WILL_NOT_DRAW) != 0
                        && (mDefaultFocusHighlight == null)
                        && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
                    mPrivateFlags |= PFLAG_SKIP_DRAW;
                }
    
                /*
                 * When the background is set, we try to apply its padding to this
                 * View. When the background is removed, we don't touch this View's
                 * padding. This is noted in the Javadocs. Hence, we don't need to
                 * requestLayout(), the invalidate() below is sufficient.
                 */
    
                // The old background's minimum size could have affected this
                // View's layout, so let's requestLayout
                requestLayout = true;
            }
    
            computeOpaqueFlags();
    
            if (requestLayout) {
                requestLayout();
            }
    
            mBackgroundSizeChanged = true;
            invalidate(true);
            invalidateOutline();
        }
    

    相关文章

      网友评论

          本文标题:记一次recyclerview item删除图片异常显示bug

          本文链接:https://www.haomeiwen.com/subject/afvykctx.html