ImageView加载图片的几种方式

setImageResource(int res)

setImageURI(int res)

setImageBitmap(int res)

setImageDrawable(Drawable)

在resolveUri中
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);
}
如果mResource!=0 --> mContext.getDrawable(mResource) 如果mUri != null --> getDrawableFromUri


通过上面的分析,可以知道
- setImageURI的方式,流程中多了几步,可能存在延时;
- setImageDrawable是流程比较少的设置方式;
- 所以,不管是setImageUri还是setImageDrawable或者setImageResource()或者setImageBitmap 都会把传递过来的对象通过resolveUri转换成一个Drawable对象,然后updateDrawable,最后invalidate绘制。
updateDrawable 在流程中这是一个重要的方法
private void updateDrawable(Drawable d) {
if (d != mRecycleableBitmapDrawable && mRecycleableBitmapDrawable != null) {
mRecycleableBitmapDrawable.setBitmap(null);
}
boolean sameDrawable = false;
if (mDrawable != null) {
sameDrawable = mDrawable == d;
mDrawable.setCallback(null);
unscheduleDrawable(mDrawable);
if (!sCompatDrawableVisibilityDispatch && !sameDrawable && isAttachedToWindow()) {
mDrawable.setVisible(false, false);
}
}
mDrawable = d;
if (d != null) {
d.setCallback(this);
d.setLayoutDirection(getLayoutDirection());
if (d.isStateful()) {
d.setState(getDrawableState());
}
if (!sameDrawable || sCompatDrawableVisibilityDispatch) {
final boolean visible = sCompatDrawableVisibilityDispatch
? getVisibility() == VISIBLE
: isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown();
d.setVisible(visible, true);
}
d.setLevel(mLevel);
mDrawableWidth = d.getIntrinsicWidth();
mDrawableHeight = d.getIntrinsicHeight();
applyImageTint();
applyColorMod();
configureBounds();
} else {
mDrawableWidth = mDrawableHeight = -1;
}
}
在mDrawable不为空的时候; 有几个方法比较重要;
1.applyImageTint:应用图片的着色模式
可以通过setImageTintMode来指定用于应用由指定的色调的混合模式 ColorStateList是模式的集合,在不设置的情况下,默认是SRC_IN(取两层绘制交集中的源图像。),总共有16中模式
2.applyColorMod//设置图片的颜色过滤
private void applyColorMod() {
if (mDrawable != null && mColorMod) {
mDrawable = mDrawable.mutate();
if (mHasColorFilter) {
mDrawable.setColorFilter(mColorFilter);
}
mDrawable.setXfermode(mXfermode);
mDrawable.setAlpha(mAlpha * mViewAlphaScale >> 8);
}
}
mColorFilter是过滤器变量,只有在发生修改时才进行变异和应用。这应该不重置mColorMod标志,因为这些过滤器需要如果更改了可拉伸部分,则重新应用。

3.configureBounds()方法配置边界
- 如果drawable没有内在尺寸,或者被告知缩放到合适的大小,然后就会填充整个视图;
- 否则。需要自己缩放,使用其本机大小;
- ScaleType的相关设置
- 最后就是在ondraw()方法中将mDrawable绘制出来。
ImageVIew设置图片的大概流程,还处于初步看源码学习,细节上没有深入,有不对之处,还望指出。