setImageResource、setImageDrawable和setImageBitmap的區別
阿新 • • 發佈:2018-12-28
最近遇到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
同樣的佈局檔案,小解析度手機:
- 使用setImageBitmap設定時,顯示如下:
2. 使用setImageResource設定時,顯示正常:
原因:
setImageResource(id)會根據裝置解析度進行圖片大小縮放適配。
setImageBitmap(BitmapFactory.decodeResource(res, id))大小需要手動調。
如果提供了完整的各種解析度下的圖片,兩種方法沒有區別。
總結
綜合來看,setImageDrawable是最省記憶體最高效的,如果擔心圖片過大或者圖片過多影響記憶體和載入效率,可以自己解析圖片然後通過呼叫setImageDrawable方法進行設定。