Problem with Android ImageView setImageDrawable not taking effect

Scenario introduction: After the system switches the theme, re-enter the app. As a result, the imageView in the app displays the default picture.
Invalid code:
mNextTurnIV.setImageDrawable(JarUtils.getResources().getDrawable(resId));

Solution: use setImageResource 

mNextTurnIV.setImageResource(resId);

Start analyzing:

1. Analyze the setImageResource source code,

       1. It is found that this method will first reset the previous drawable object.
       2. It will save the resId to the memory.

       3. The drawable object will be reloaded in the resource and set.

 @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); //   1.发现该方法会先重置之前的drawable对象,
        mResource = resId;    //    2. 会保存 resId 到内存中 ,
        mUri = null;

        resolveUri();   //3.会重新在resource中重新加载drawable对象并设置

        if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
            requestLayout();
        }
        invalidate();
    }

   4. Finally, the drawable object will be set into the ImageView 

 @UnsupportedAppUsage
    private void resolveUri() {
        if (mDrawable != null) {
            return;
        }

        if (getResources() == null) {
            return;
        }

        Drawable d = null;

        if (mResource != 0) {
            try {
                d = mContext.getDrawable(mResource);
            } catch (Exception e) {
                Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);
                // Don't try again.
                mResource = 0;
            }
        } else if (mUri != null) {
            d = getDrawableFromUri(mUri);

            if (d == null) {
                Log.w(LOG_TAG, "resolveUri failed on bad bitmap uri: " + mUri);
                // Don't try again.
                mUri = null;
            }
        } else {
            return;
        }

        updateDrawable(d); // 4.最后会把得到drawable对象设置进ImageView中
    }

2. Analyze the setImageDrawable source code,

        1. First, the previous drawable object and the previous drawable object will be judged. If they are inconsistent, execute

         2. After successful execution, mResource will be set to 0

    public void setImageDrawable(@Nullable Drawable drawable) {
        // 1.首先会判断之前的drawable对象和之前的drawable对象,如果不一致则执行
        if (mDrawable != drawable) {
            mResource = 0; // 2.执行成功后 会把mResource设置为0
            mUri = null;

            final int oldWidth = mDrawableWidth;
            final int oldHeight = mDrawableHeight;

            updateDrawable(drawable);

            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
                requestLayout();
            }
            invalidate();
        }
    }

Final feasibility conclusion:

        The system switches the theme, resulting in a series of resets and updates. After entering the app again, the ImageView will redraw the drawable image based on the mResource in the memory. Since the setImageDrawable method is successfully set, the mResource in the ImageView will be reset to 0, so this causes The default drawable object is drawn, but the setImageDrawable does not take effect.

        The setImageResource method will set the mResource in the ImageView to the previously set resId each time, so after entering the app, the ImageView will draw the previous picture based on the mResource saved in the memory, so there will be no problem.

Guess you like

Origin blog.csdn.net/chengzhenjia/article/details/131583195