场景介绍:在系统切换主题之后,重新进入app,结果app中的imageView显示的是默认的图片 不生效代码:
mNextTurnIV.setImageDrawable(JarUtils.getResources().getDrawable(resId));
解决:使用 setImageResource
mNextTurnIV.setImageResource(resId);
开始剖析:
一. 分析setImageResource源码,
1.发现该方法会先重置之前的drawable对象,
2. 会保存 resId 到内存中 ,
3.会重新在resource中重新加载drawable对象并设置,
@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.最后会把得到drawable对象设置进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中
}
二. 分析setImageDrawable源码,
1.首先会判断之前的drawable对象和之前的drawable对象,如果不一致则执行
2.执行成功后 会把mResource设置为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();
}
}
最终可行性结论:
系统切换主题导致一系列重置和update在中间的过程中,再次进入app后ImageView会根据内存中mResource重新绘制drawable图片,由于setImageDrawable方法设置成功后会把ImageView中的mResource重置为0,所以导致绘制了默认的drawable对象,而产出setImageDrawable不生效的问题。
而setImageResource方法每次后会把ImageView中的mResource设置为之前设置的resId,所以在此进入app后ImageView会根据内存的保存的mResource绘制之前的图片所以不会有问题。