setImageResource、setImageDrawable和setImageBitmap的区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011386173/article/details/83303032

最近遇到ImageView控件设置的图片延迟才显示的问题(虽然最终发现原因是图片是全透明的)。

顺势跟踪了一下给ImageView设置图片的源码。

以下分析都是基于Android8.0

setImageResource

源码中对该接口的注释:

    /**
     * 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.
       .....
    }

在UI线程中处理bitmap,这可能造成主线程的延迟(如导致Activity启动延迟等情况)。

可以考虑使用setImageDrawable(Drawable)或setImageBitmap(Bitmap)代替。

setImageDrawable

    /**
     * Sets a drawable as the content of this ImageView.
     *
     * @param drawable the Drawable to set, or {@code null} to clear the
     *                 content
     */
    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();
        }
    }

setImageDrawable(null)可以清除一个ImageView控件设置的图片。

setImageBitmap

    /**
     * Sets a Bitmap as the content of this ImageView.
     *
     * @param bm The bitmap to set
     */
    @android.view.RemotableViewMethod
    public void setImageBitmap(Bitmap bm) {
        // Hacky fix to force setImageDrawable to do a full setImageDrawable
        // instead of doing an object reference comparison
        mDrawable = null;
        if (mRecycleableBitmapDrawable == null) {
            mRecycleableBitmapDrawable = new BitmapDrawable(mContext.getResources(), bm);
        } else {
            mRecycleableBitmapDrawable.setBitmap(bm);
        }
        setImageDrawable(mRecycleableBitmapDrawable);
    }

setImageBitmap实际还是调用的setImageDrawable,但是强制setImageDrawble执行完整的setImageDrawable而不是做对象引用比较。setImageBitmap将Bitmap对象封装成Drawable对象,

setImageBitmap和setImageDrawable的区别

参考自https://blog.csdn.net/zhaoyazhi2129/article/details/32080827

同样的布局文件,小分辨率手机:

  1. 使用setImageBitmap设置时,显示如下:

  2. 使用setImageResource设置时,显示正常:

原因:

setImageResource(id)会根据设备分辨率进行图片大小缩放适配。

setImageBitmap(BitmapFactory.decodeResource(res, id))大小需要手动调。

如果提供了完整的各种分辨率下的图片,两种方法没有区别。

总结

综合来看,setImageDrawable是最省内存最高效的,如果担心图片过大或者图片过多影响内存和加载效率,可以自己解析图片然后通过调用setImageDrawable方法进行设置。

猜你喜欢

转载自blog.csdn.net/u011386173/article/details/83303032
今日推荐