对大多数Android的开发者来说,最经常的操作莫过于对界面进行布局,View中背景图片的加载是最经常做的。但是我们很少关注这个过程,这篇文章主要解析view中背景图片加载的流程。了解view中背景图片的加载(资源的加载)可以让我们对资源加载的过程进行一些优化,另外当需要进行整个应用的换肤时,也可以更得心应手。dHGHTML5中文学习网 - HTML5先行者学习网
View图片的加载,我们最常见的就是通过在XML文件当中进行drawable的设置,然后让Android系统帮我们完成,或者手动写代码加载成Bitmap,然后加载到View上。这篇文章主要分析Android在什么时候以及怎么帮我们完成背景图片的加载的,那么我们就从Activity.setContentView还是LayoutInflater.inflate(...)方法开始分析。dHGHTML5中文学习网 - HTML5先行者学习网
不管是从Activity.setContentView(...)还是LayoutInflater.inflate(...)方法进行View的初始化,最终都会到达LayoutInflater.inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)这个方法中。在这里我们主要关注View的背景图片加载,对于XML如何解析和加载就放过了。dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {dHGHTML5中文学习网 - HTML5先行者学习网
synchronized (mConstructorArgs) {dHGHTML5中文学习网 - HTML5先行者学习网
final AttributeSet attrs = Xml.asAttributeSet(parser);dHGHTML5中文学习网 - HTML5先行者学习网
Context lastContext = (Context)mConstructorArgs[0];dHGHTML5中文学习网 - HTML5先行者学习网
mConstructorArgs[0] = mContext;dHGHTML5中文学习网 - HTML5先行者学习网
View result = root;dHGHTML5中文学习网 - HTML5先行者学习网
try {dHGHTML5中文学习网 - HTML5先行者学习网
// Look for the root node.dHGHTML5中文学习网 - HTML5先行者学习网
int type;dHGHTML5中文学习网 - HTML5先行者学习网
while ((type = parser.next()) != XmlPullParser.START_TAG &&dHGHTML5中文学习网 - HTML5先行者学习网
type != XmlPullParser.END_DOCUMENT) {dHGHTML5中文学习网 - HTML5先行者学习网
// EmptydHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (type != XmlPullParser.START_TAG) {dHGHTML5中文学习网 - HTML5先行者学习网
throw new InflateException(parser.getPositionDescription()dHGHTML5中文学习网 - HTML5先行者学习网
+ ": No start tag found!");dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
final String name = parser.getName();dHGHTML5中文学习网 - HTML5先行者学习网
if (DEBUG) {dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("**************************");dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("Creating root view: "dHGHTML5中文学习网 - HTML5先行者学习网
+ name);dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("**************************");dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (TAG_MERGE.equals(name)) {dHGHTML5中文学习网 - HTML5先行者学习网
if (root == null || !attachToRoot) {dHGHTML5中文学习网 - HTML5先行者学习网
throw new InflateException("<merge /> can be used only with a valid "dHGHTML5中文学习网 - HTML5先行者学习网
+ "ViewGroup root and attachToRoot=true");dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
rInflate(parser, root, attrs, false);dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
// Temp is the root view that was found in the xmldHGHTML5中文学习网 - HTML5先行者学习网
View temp;dHGHTML5中文学习网 - HTML5先行者学习网
if (TAG_1995.equals(name)) {dHGHTML5中文学习网 - HTML5先行者学习网
temp = new BlinkLayout(mContext, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
temp = createViewFromTag(root, name, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
ViewGroup.LayoutParams params = null;dHGHTML5中文学习网 - HTML5先行者学习网
if (root != null) {dHGHTML5中文学习网 - HTML5先行者学习网
if (DEBUG) {dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("Creating params from root: " +dHGHTML5中文学习网 - HTML5先行者学习网
root);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
// Create layout params that match root, if supplieddHGHTML5中文学习网 - HTML5先行者学习网
params = root.generateLayoutParams(attrs);dHGHTML5中文学习网 - HTML5先行者学习网
if (!attachToRoot) {dHGHTML5中文学习网 - HTML5先行者学习网
// Set the layout params for temp if we are notdHGHTML5中文学习网 - HTML5先行者学习网
// attaching. (If we are, we use addView, below)dHGHTML5中文学习网 - HTML5先行者学习网
temp.setLayoutParams(params);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (DEBUG) {dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("-----> start inflating children");dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
// Inflate all children under tempdHGHTML5中文学习网 - HTML5先行者学习网
rInflate(parser, temp, attrs, true);dHGHTML5中文学习网 - HTML5先行者学习网
if (DEBUG) {dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("-----> done inflating children");dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
// We are supposed to attach all the views we found (int temp)dHGHTML5中文学习网 - HTML5先行者学习网
// to root. Do that now.dHGHTML5中文学习网 - HTML5先行者学习网
if (root != null && attachToRoot) {dHGHTML5中文学习网 - HTML5先行者学习网
root.addView(temp, params);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
// Decide whether to return the root that was passed in or thedHGHTML5中文学习网 - HTML5先行者学习网
// top view found in xml.dHGHTML5中文学习网 - HTML5先行者学习网
if (root == null || !attachToRoot) {dHGHTML5中文学习网 - HTML5先行者学习网
result = temp;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
} catch (XmlPullParserException e) {dHGHTML5中文学习网 - HTML5先行者学习网
InflateException ex = new InflateException(e.getMessage());dHGHTML5中文学习网 - HTML5先行者学习网
ex.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw ex;dHGHTML5中文学习网 - HTML5先行者学习网
} catch (IOException e) {dHGHTML5中文学习网 - HTML5先行者学习网
InflateException ex = new InflateException(dHGHTML5中文学习网 - HTML5先行者学习网
parser.getPositionDescription()dHGHTML5中文学习网 - HTML5先行者学习网
+ ": " + e.getMessage());dHGHTML5中文学习网 - HTML5先行者学习网
ex.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw ex;dHGHTML5中文学习网 - HTML5先行者学习网
} finally {dHGHTML5中文学习网 - HTML5先行者学习网
// Don't retain static reference on context.dHGHTML5中文学习网 - HTML5先行者学习网
mConstructorArgs[0] = lastContext;dHGHTML5中文学习网 - HTML5先行者学习网
mConstructorArgs[1] = null;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
return result;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
上面这么长一串代码,其实思路很清晰,就是针对XML文件进行解析,然后根据XML解析出的每一个节点进行View的初始化,紧接着将View的Layout参数设置到View上,然后将View添加到它的父控件上。dHGHTML5中文学习网 - HTML5先行者学习网
为了了解View是怎么被加载出来的,我们只需要了解dHGHTML5中文学习网 - HTML5先行者学习网
temp = createViewFromTag(root, name, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
跟进去看看。dHGHTML5中文学习网 - HTML5先行者学习网
/*dHGHTML5中文学习网 - HTML5先行者学习网
* default visibility so the BridgeInflater can override it.dHGHTML5中文学习网 - HTML5先行者学习网
*/dHGHTML5中文学习网 - HTML5先行者学习网
View createViewFromTag(View parent, String name, AttributeSet attrs) {dHGHTML5中文学习网 - HTML5先行者学习网
if (name.equals("view")) {dHGHTML5中文学习网 - HTML5先行者学习网
name = attrs.getAttributeValue(null, "class");dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (DEBUG) System.out.println("******** Creating view: " + name);dHGHTML5中文学习网 - HTML5先行者学习网
try {dHGHTML5中文学习网 - HTML5先行者学习网
View view;dHGHTML5中文学习网 - HTML5先行者学习网
if (mFactory2 != null) view = mFactory2.onCreateView(parent, name, mContext, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
else if (mFactory != null) view = mFactory.onCreateView(name, mContext, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
else view = null;dHGHTML5中文学习网 - HTML5先行者学习网
if (view == null && mPrivateFactory != null) {dHGHTML5中文学习网 - HTML5先行者学习网
view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (view == null) {dHGHTML5中文学习网 - HTML5先行者学习网
if (-1 == name.indexOf('.')) {dHGHTML5中文学习网 - HTML5先行者学习网
view = onCreateView(parent, name, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
view = createView(name, null, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (DEBUG) System.out.println("Created view is: " + view);dHGHTML5中文学习网 - HTML5先行者学习网
return view;dHGHTML5中文学习网 - HTML5先行者学习网
} catch (InflateException e) {dHGHTML5中文学习网 - HTML5先行者学习网
throw e;dHGHTML5中文学习网 - HTML5先行者学习网
} catch (ClassNotFoundException e) {dHGHTML5中文学习网 - HTML5先行者学习网
InflateException ie = new InflateException(attrs.getPositionDescription()dHGHTML5中文学习网 - HTML5先行者学习网
+ ": Error inflating class " + name);dHGHTML5中文学习网 - HTML5先行者学习网
ie.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw ie;dHGHTML5中文学习网 - HTML5先行者学习网
} catch (Exception e) {dHGHTML5中文学习网 - HTML5先行者学习网
InflateException ie = new InflateException(attrs.getPositionDescription()dHGHTML5中文学习网 - HTML5先行者学习网
+ ": Error inflating class " + name);dHGHTML5中文学习网 - HTML5先行者学习网
ie.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw ie;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网上面代码的重点在于try...Catch里的内容。try包起来的东西就是对View进行初始化,注意到上面代码中有几个Factory,这些Factory可以在View进行初始化,也就是说其实我们可以在这里干预View的初始化。从上面代码我们可以知道,如果我们自定义了一个Factory,那么当前要初始化的View会优先被我们自定义的Factory初始化,而不通过系统默认的Factory初始化。那么如果我们要自定义Factory,应该在哪里定义呢?容易想到,Factory必须要赶在资源加载前自定义完成,所以我们应该在onCreate(...)的this.setContentView(...)之前设置LayoutInflater.Factory。dHGHTML5中文学习网 - HTML5先行者学习网
getLayoutInflater().setFactory(factory);dHGHTML5中文学习网 - HTML5先行者学习网
接下来我们看到上面函数里面的dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网
if (-1 == name.indexOf('.')) {dHGHTML5中文学习网 - HTML5先行者学习网
view = onCreateView(parent, name, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
view = createView(name, null, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网这段函数就是对View进行初始化,有两种情况,一种是系统自带的View,它在dHGHTML5中文学习网 - HTML5先行者学习网
if (-1 == name.indexOf('.'))dHGHTML5中文学习网 - HTML5先行者学习网
这里面进行初始化,因为如果是系统自带的View,传入的那么一般不带系统的前缀"android.view."。另一个分支初始化的是我们自定义的View。我们跟进onCreateView看看。dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网
protected View onCreateView(String name, AttributeSet attrs)dHGHTML5中文学习网 - HTML5先行者学习网
throws ClassNotFoundException {dHGHTML5中文学习网 - HTML5先行者学习网
return createView(name, "android.view.", attrs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
public final View createView(String name, String prefix, AttributeSet attrs)dHGHTML5中文学习网 - HTML5先行者学习网
throws ClassNotFoundException, InflateException {dHGHTML5中文学习网 - HTML5先行者学习网
Constructor<? extends View> constructor = sConstructorMap.get(name);dHGHTML5中文学习网 - HTML5先行者学习网
Class<? extends View> clazz = null;dHGHTML5中文学习网 - HTML5先行者学习网
try {dHGHTML5中文学习网 - HTML5先行者学习网
if (constructor == null) {dHGHTML5中文学习网 - HTML5先行者学习网
// Class not found in the cache, see if it's real, and try to add itdHGHTML5中文学习网 - HTML5先行者学习网
clazz = mContext.getClassLoader().loadClass(dHGHTML5中文学习网 - HTML5先行者学习网
prefix != null ? (prefix + name) : name).asSubclass(View.class);dHGHTML5中文学习网 - HTML5先行者学习网
if (mFilter != null && clazz != null) {dHGHTML5中文学习网 - HTML5先行者学习网
boolean allowed = mFilter.onLoadClass(clazz);dHGHTML5中文学习网 - HTML5先行者学习网
if (!allowed) {dHGHTML5中文学习网 - HTML5先行者学习网
failNotAllowed(name, prefix, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
constructor = clazz.getConstructor(mConstructorSignature);dHGHTML5中文学习网 - HTML5先行者学习网
sConstructorMap.put(name, constructor);dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
// If we have a filter, apply it to cached constructordHGHTML5中文学习网 - HTML5先行者学习网
if (mFilter != null) {dHGHTML5中文学习网 - HTML5先行者学习网
// Have we seen this name before?dHGHTML5中文学习网 - HTML5先行者学习网
Boolean allowedState = mFilterMap.get(name);dHGHTML5中文学习网 - HTML5先行者学习网
if (allowedState == null) {dHGHTML5中文学习网 - HTML5先行者学习网
// New class -- remember whether it is alloweddHGHTML5中文学习网 - HTML5先行者学习网
clazz = mContext.getClassLoader().loadClass(dHGHTML5中文学习网 - HTML5先行者学习网
prefix != null ? (prefix + name) : name).asSubclass(View.class);dHGHTML5中文学习网 - HTML5先行者学习网
boolean allowed = clazz != null && mFilter.onLoadClass(clazz);dHGHTML5中文学习网 - HTML5先行者学习网
mFilterMap.put(name, allowed);dHGHTML5中文学习网 - HTML5先行者学习网
if (!allowed) {dHGHTML5中文学习网 - HTML5先行者学习网
failNotAllowed(name, prefix, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
} else if (allowedState.equals(Boolean.FALSE)) {dHGHTML5中文学习网 - HTML5先行者学习网
failNotAllowed(name, prefix, attrs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
Object[] args = mConstructorArgs;dHGHTML5中文学习网 - HTML5先行者学习网
args[1] = attrs;dHGHTML5中文学习网 - HTML5先行者学习网
final View view = constructor.newInstance(args);dHGHTML5中文学习网 - HTML5先行者学习网
if (view instanceof ViewStub) {dHGHTML5中文学习网 - HTML5先行者学习网
// always use ourselves when inflating ViewStub laterdHGHTML5中文学习网 - HTML5先行者学习网
final ViewStub viewStub = (ViewStub) view;dHGHTML5中文学习网 - HTML5先行者学习网
viewStub.setLayoutInflater(this);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
return view;dHGHTML5中文学习网 - HTML5先行者学习网
} catch (NoSuchMethodException e) {dHGHTML5中文学习网 - HTML5先行者学习网
InflateException ie = new InflateException(attrs.getPositionDescription()dHGHTML5中文学习网 - HTML5先行者学习网
+ ": Error inflating class "dHGHTML5中文学习网 - HTML5先行者学习网
+ (prefix != null ? (prefix + name) : name));dHGHTML5中文学习网 - HTML5先行者学习网
ie.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw ie;dHGHTML5中文学习网 - HTML5先行者学习网
} catch (ClassCastException e) {dHGHTML5中文学习网 - HTML5先行者学习网
// If loaded class is not a View subclassdHGHTML5中文学习网 - HTML5先行者学习网
InflateException ie = new InflateException(attrs.getPositionDescription()dHGHTML5中文学习网 - HTML5先行者学习网
+ ": Class is not a View "dHGHTML5中文学习网 - HTML5先行者学习网
+ (prefix != null ? (prefix + name) : name));dHGHTML5中文学习网 - HTML5先行者学习网
ie.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw ie;dHGHTML5中文学习网 - HTML5先行者学习网
} catch (ClassNotFoundException e) {dHGHTML5中文学习网 - HTML5先行者学习网
// If loadClass fails, we should propagate the exception.dHGHTML5中文学习网 - HTML5先行者学习网
throw e;dHGHTML5中文学习网 - HTML5先行者学习网
} catch (Exception e) {dHGHTML5中文学习网 - HTML5先行者学习网
InflateException ie = new InflateException(attrs.getPositionDescription()dHGHTML5中文学习网 - HTML5先行者学习网
+ ": Error inflating class "dHGHTML5中文学习网 - HTML5先行者学习网
+ (clazz == null ? "<unknown>" : clazz.getName()));dHGHTML5中文学习网 - HTML5先行者学习网
ie.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw ie;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网从onCreateView(...)中我们知道,其实createViewFromTag(...)中对View的初始化最终都是通过createView(...)这个函数进行初始化的,不同只在于系统控件需要通过onCreateView(...)加上前缀,以便类加载器(ClassLoader)正确地通过类所在的包初始化这个类。createView(...)这个函数的思路很清晰,不看catch里面的内容,try里面开头的两个分支就是用来将所要用的类构造函数提取出来,Android系统会对使用过的类构造函数进行缓存,因为像TextView这些常用的控件可能会被使用很多次。接下来,就是通过类构造函数对View进行初始化了。我们注意到传入构造函数的mConstructorArgs是一个包含两个元素的数组。dHGHTML5中文学习网 - HTML5先行者学习网
final Object[] mConstructorArgs = new Object[2];dHGHTML5中文学习网 - HTML5先行者学习网
那么我们就很清楚了,它就是调用系统控件中对应两个参数的构造函数。为了方便,我们就从最基础的View进行分析。dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网
public View(Context context, AttributeSet attrs) {dHGHTML5中文学习网 - HTML5先行者学习网
this(context, attrs, 0);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
public View(Context context, AttributeSet attrs, int defStyle) {dHGHTML5中文学习网 - HTML5先行者学习网
this(context);dHGHTML5中文学习网 - HTML5先行者学习网
TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,dHGHTML5中文学习网 - HTML5先行者学习网
defStyle, 0);dHGHTML5中文学习网 - HTML5先行者学习网
Drawable background = null;dHGHTML5中文学习网 - HTML5先行者学习网
int leftPadding = -1;dHGHTML5中文学习网 - HTML5先行者学习网
int topPadding = -1;dHGHTML5中文学习网 - HTML5先行者学习网
int rightPadding = -1;dHGHTML5中文学习网 - HTML5先行者学习网
int bottomPadding = -1;dHGHTML5中文学习网 - HTML5先行者学习网
int startPadding = UNDEFINED_PADDING;dHGHTML5中文学习网 - HTML5先行者学习网
int endPadding = UNDEFINED_PADDING;dHGHTML5中文学习网 - HTML5先行者学习网
int padding = -1;dHGHTML5中文学习网 - HTML5先行者学习网
int viewFlagValues = 0;dHGHTML5中文学习网 - HTML5先行者学习网
int viewFlagMasks = 0;dHGHTML5中文学习网 - HTML5先行者学习网
boolean setScrollContainer = false;dHGHTML5中文学习网 - HTML5先行者学习网
int x = 0;dHGHTML5中文学习网 - HTML5先行者学习网
int y = 0;dHGHTML5中文学习网 - HTML5先行者学习网
float tx = 0;dHGHTML5中文学习网 - HTML5先行者学习网
float ty = 0;dHGHTML5中文学习网 - HTML5先行者学习网
float rotation = 0;dHGHTML5中文学习网 - HTML5先行者学习网
float rotationX = 0;dHGHTML5中文学习网 - HTML5先行者学习网
float rotationY = 0;dHGHTML5中文学习网 - HTML5先行者学习网
float sx = 1f;dHGHTML5中文学习网 - HTML5先行者学习网
float sy = 1f;dHGHTML5中文学习网 - HTML5先行者学习网
boolean transformSet = false;dHGHTML5中文学习网 - HTML5先行者学习网
int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;dHGHTML5中文学习网 - HTML5先行者学习网
int overScrollMode = mOverScrollMode;dHGHTML5中文学习网 - HTML5先行者学习网
boolean initializeScrollbars = false;dHGHTML5中文学习网 - HTML5先行者学习网
boolean leftPaddingDefined = false;dHGHTML5中文学习网 - HTML5先行者学习网
boolean rightPaddingDefined = false;dHGHTML5中文学习网 - HTML5先行者学习网
boolean startPaddingDefined = false;dHGHTML5中文学习网 - HTML5先行者学习网
boolean endPaddingDefined = false;dHGHTML5中文学习网 - HTML5先行者学习网
final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;dHGHTML5中文学习网 - HTML5先行者学习网
final int N = a.getIndexCount();dHGHTML5中文学习网 - HTML5先行者学习网
for (int i = 0; i < N; i++) {dHGHTML5中文学习网 - HTML5先行者学习网
int attr = a.getIndex(i);dHGHTML5中文学习网 - HTML5先行者学习网
switch (attr) {dHGHTML5中文学习网 - HTML5先行者学习网
case com.android.internal.R.styleable.View_background:dHGHTML5中文学习网 - HTML5先行者学习网
background = a.getDrawable(attr);dHGHTML5中文学习网 - HTML5先行者学习网
break;dHGHTML5中文学习网 - HTML5先行者学习网
case com.android.internal.R.styleable.View_padding:dHGHTML5中文学习网 - HTML5先行者学习网
padding = a.getDimensionPixelSize(attr, -1);dHGHTML5中文学习网 - HTML5先行者学习网
mUserPaddingLeftInitial = padding;dHGHTML5中文学习网 - HTML5先行者学习网
mUserPaddingRightInitial = padding;dHGHTML5中文学习网 - HTML5先行者学习网
leftPaddingDefined = true;dHGHTML5中文学习网 - HTML5先行者学习网
rightPaddingDefined = true;dHGHTML5中文学习网 - HTML5先行者学习网
break;dHGHTML5中文学习网 - HTML5先行者学习网
//省略一大串无关的函数dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网由于我们只关注View中的背景图是怎么加载的,注意这个函数其实就是遍历AttributeSet attrs这个东西,然后对View的各个属性进行初始化。我们直接进入dHGHTML5中文学习网 - HTML5先行者学习网
background = a.getDrawable(attr);dHGHTML5中文学习网 - HTML5先行者学习网
这里看看(TypedArray.getDrawable)。dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网
public Drawable getDrawable(int index) {dHGHTML5中文学习网 - HTML5先行者学习网
final TypedValue value = mValue;dHGHTML5中文学习网 - HTML5先行者学习网
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {dHGHTML5中文学习网 - HTML5先行者学习网
if (false) {dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("******************************************************************");dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("Got drawable resource: type="dHGHTML5中文学习网 - HTML5先行者学习网
+ value.typedHGHTML5中文学习网 - HTML5先行者学习网
+ " str=" + value.stringdHGHTML5中文学习网 - HTML5先行者学习网
+ " int=0x" + Integer.toHexString(value.data)dHGHTML5中文学习网 - HTML5先行者学习网
+ " cookie=" + value.assetCookie);dHGHTML5中文学习网 - HTML5先行者学习网
System.out.println("******************************************************************");dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
return mResources.loadDrawable(value, value.resourceId);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
return null;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网我们发现它调用mResources.loadDrawable(...),进去看看。dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网
/*package*/ Drawable loadDrawable(TypedValue value, int id)dHGHTML5中文学习网 - HTML5先行者学习网
throws NotFoundException {dHGHTML5中文学习网 - HTML5先行者学习网
if (TRACE_FOR_PRELOAD) {dHGHTML5中文学习网 - HTML5先行者学习网
// Log only framework resourcesdHGHTML5中文学习网 - HTML5先行者学习网
if ((id >>> 24) == 0x1) {dHGHTML5中文学习网 - HTML5先行者学习网
final String name = getResourceName(id);dHGHTML5中文学习网 - HTML5先行者学习网
if (name != null) android.util.Log.d("PreloadDrawable", name);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
boolean isColorDrawable = false;dHGHTML5中文学习网 - HTML5先行者学习网
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&dHGHTML5中文学习网 - HTML5先行者学习网
value.type <= TypedValue.TYPE_LAST_COLOR_INT) {dHGHTML5中文学习网 - HTML5先行者学习网
isColorDrawable = true;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
final long key = isColorDrawable ? value.data :dHGHTML5中文学习网 - HTML5先行者学习网
(((long) value.assetCookie) << 32) | value.data;dHGHTML5中文学习网 - HTML5先行者学习网
Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);dHGHTML5中文学习网 - HTML5先行者学习网
if (dr != null) {dHGHTML5中文学习网 - HTML5先行者学习网
return dr;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
Drawable.ConstantState cs = isColorDrawabledHGHTML5中文学习网 - HTML5先行者学习网
? sPreloadedColorDrawables.get(key)dHGHTML5中文学习网 - HTML5先行者学习网
: (sPreloadedDensity == mConfiguration.densityDpidHGHTML5中文学习网 - HTML5先行者学习网
? sPreloadedDrawables.get(key) : null);dHGHTML5中文学习网 - HTML5先行者学习网
if (cs != null) {dHGHTML5中文学习网 - HTML5先行者学习网
dr = cs.newDrawable(this);dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
if (isColorDrawable) {dHGHTML5中文学习网 - HTML5先行者学习网
dr = new ColorDrawable(value.data);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (dr == null) {dHGHTML5中文学习网 - HTML5先行者学习网
if (value.string == null) {dHGHTML5中文学习网 - HTML5先行者学习网
throw new NotFoundException(dHGHTML5中文学习网 - HTML5先行者学习网
"Resource is not a Drawable (color or path): " + value);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
String file = value.string.toString();dHGHTML5中文学习网 - HTML5先行者学习网
if (TRACE_FOR_MISS_PRELOAD) {dHGHTML5中文学习网 - HTML5先行者学习网
// Log only framework resourcesdHGHTML5中文学习网 - HTML5先行者学习网
if ((id >>> 24) == 0x1) {dHGHTML5中文学习网 - HTML5先行者学习网
final String name = getResourceName(id);dHGHTML5中文学习网 - HTML5先行者学习网
if (name != null) android.util.Log.d(TAG, "Loading framework drawable #"dHGHTML5中文学习网 - HTML5先行者学习网
+ Integer.toHexString(id) + ": " + namedHGHTML5中文学习网 - HTML5先行者学习网
+ " at " + file);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "dHGHTML5中文学习网 - HTML5先行者学习网
+ value.assetCookie + ": " + file);dHGHTML5中文学习网 - HTML5先行者学习网
if (file.endsWith(".xml")) {dHGHTML5中文学习网 - HTML5先行者学习网
try {dHGHTML5中文学习网 - HTML5先行者学习网
XmlResourceParser rp = loadXmlResourceParser(dHGHTML5中文学习网 - HTML5先行者学习网
file, id, value.assetCookie, "drawable");dHGHTML5中文学习网 - HTML5先行者学习网
dr = Drawable.createFromXml(this, rp);dHGHTML5中文学习网 - HTML5先行者学习网
rp.close();dHGHTML5中文学习网 - HTML5先行者学习网
} catch (Exception e) {dHGHTML5中文学习网 - HTML5先行者学习网
NotFoundException rnf = new NotFoundException(dHGHTML5中文学习网 - HTML5先行者学习网
"File " + file + " from drawable resource ID #0x"dHGHTML5中文学习网 - HTML5先行者学习网
+ Integer.toHexString(id));dHGHTML5中文学习网 - HTML5先行者学习网
rnf.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw rnf;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
try {dHGHTML5中文学习网 - HTML5先行者学习网
InputStream is = mAssets.openNonAsset(dHGHTML5中文学习网 - HTML5先行者学习网
value.assetCookie, file, AssetManager.ACCESS_STREAMING);dHGHTML5中文学习网 - HTML5先行者学习网
// System.out.println("Opened file " + file + ": " + is);dHGHTML5中文学习网 - HTML5先行者学习网
dr = Drawable.createFromResourceStream(this, value, is,dHGHTML5中文学习网 - HTML5先行者学习网
file, null);dHGHTML5中文学习网 - HTML5先行者学习网
is.close();dHGHTML5中文学习网 - HTML5先行者学习网
// System.out.println("Created stream: " + dr);dHGHTML5中文学习网 - HTML5先行者学习网
} catch (Exception e) {dHGHTML5中文学习网 - HTML5先行者学习网
NotFoundException rnf = new NotFoundException(dHGHTML5中文学习网 - HTML5先行者学习网
"File " + file + " from drawable resource ID #0x"dHGHTML5中文学习网 - HTML5先行者学习网
+ Integer.toHexString(id));dHGHTML5中文学习网 - HTML5先行者学习网
rnf.initCause(e);dHGHTML5中文学习网 - HTML5先行者学习网
throw rnf;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
if (dr != null) {dHGHTML5中文学习网 - HTML5先行者学习网
dr.setChangingConfigurations(value.changingConfigurations);dHGHTML5中文学习网 - HTML5先行者学习网
cs = dr.getConstantState();dHGHTML5中文学习网 - HTML5先行者学习网
if (cs != null) {dHGHTML5中文学习网 - HTML5先行者学习网
if (mPreloading) {dHGHTML5中文学习网 - HTML5先行者学习网
if (verifyPreloadConfig(value, "drawable")) {dHGHTML5中文学习网 - HTML5先行者学习网
if (isColorDrawable) {dHGHTML5中文学习网 - HTML5先行者学习网
sPreloadedColorDrawables.put(key, cs);dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
sPreloadedDrawables.put(key, cs);dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
synchronized (mTmpValue) {dHGHTML5中文学习网 - HTML5先行者学习网
//Log.i(TAG, "Saving cached drawable @ #" +dHGHTML5中文学习网 - HTML5先行者学习网
// Integer.toHexString(key.intValue())dHGHTML5中文学习网 - HTML5先行者学习网
// + " in " + this + ": " + cs);dHGHTML5中文学习网 - HTML5先行者学习网
if (isColorDrawable) {dHGHTML5中文学习网 - HTML5先行者学习网
mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));dHGHTML5中文学习网 - HTML5先行者学习网
} else {dHGHTML5中文学习网 - HTML5先行者学习网
mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
return dr;dHGHTML5中文学习网 - HTML5先行者学习网
}dHGHTML5中文学习网 - HTML5先行者学习网
dHGHTML5中文学习网 - HTML5先行者学习网就是这个函数了,所有View的背景的加载都在这里了。这个函数的逻辑就比较复杂了,大体说来就是根据背景的类型(纯颜色、定义在XML文件中的,或者是一张静态的背景),如果缓存里面有,就直接用缓存里的。dHGHTML5中文学习网 - HTML5先行者学习网
总结一下,经过上面的分析,我们知道了,Android就是在Activity.setContentView(...)中为我们进行资源文件的加载,精确到具体的函数的话,资源文件的加载就是在每一个被初始化的View的构造函数中进行加载的。dHGHTML5中文学习网 - HTML5先行者学习网
以上就是本文的全部内容了,希望对大家能够有所帮助。dHGHTML5中文学习网 - HTML5先行者学习网