Drawable Xml资源文件解析过程
从drawable资源文件获取一个drawable对象,是通过调用Resources.getDrawable(int)
方法实现。该方法主要流程如下:
// Resources.java
public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
throws NotFoundException {
...
return mResourcesImpl.loadDrawable(this, value, id, theme, true);
...
}
// ResourcesImpl.java
@Nullable
Drawable loadDrawable(Resources wrapper, TypedValue value, int id, Resources.Theme theme,boolean useCache) throws NotFoundException {
...
// Cache相关
Drawable dr;
if (isColorDrawable) {
dr = new ColorDrawable(value.data); // ColorDrawable
} else {
dr = loadDrawableForCookie(wrapper, value, id, null);
}
...
}
private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id, Resources.Theme theme) {
...
if (file.endsWith(".xml")) {
// 创建XmlResourceParser
Drawable.createFromXml(wrapper, rp, theme);
} else {
Drawable.createFromResourceStream(wrapper, value, is, file, null);
}
...
}
最终进入Drawable
类中
// Drawable.java
public static Drawable createFromXml(Resources r, XmlPullParser parser, Theme theme) throws XmlPullParserException, IOException {
...
Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
...
return drawable
}
中间一系列的方法委托转发等调用后
// **.java
@NonNull
public Drawable inflateFromXml(@NonNull String name, @NonNull XmlPullParser parser,
@NonNull AttributeSet attrs, @Nullable Theme theme)
throws XmlPullParserException, IOException {
// Inner classes must be referenced as Outer$Inner, but XML tag names
// can't contain $, so the <drawable> tag allows developers to specify
// the class in an attribute. We'll still run it through inflateFromTag
// to stay consistent with how LayoutInflater works.
if (name.equals("drawable")) {
// 解析自定义drawable类型
name = attrs.getAttributeValue(null, "class");
if (name == null) {
throw new InflateException("<drawable> tag must specify class attribute");
}
}
// 通过根标签名创建对应Drawable实现类对象
Drawable drawable = inflateFromTag(name);
if (drawable == null) {
// 是自定义的drawable,反射创建类实现
drawable = inflateFromClass(name);
}
// xml子标签的解析交给具体drawable实现类处理
drawable.inflate(mRes, parser, attrs, theme);
return drawable;
}
private Drawable inflateFromTag(@NonNull String name) {
switch (name) {
case "selector":
return new StateListDrawable();
case "animated-selector":
return new AnimatedStateListDrawable();
case "level-list":
return new LevelListDrawable();
case "layer-list":
return new LayerDrawable();
case "transition":
return new TransitionDrawable();
case "ripple":
return new RippleDrawable();
case "color":
return new ColorDrawable();
case "shape":
return new GradientDrawable();
case "vector":
return new VectorDrawable();
case "animated-vector":
return new AnimatedVectorDrawable();
case "scale":
return new ScaleDrawable();
case "clip":
return new ClipDrawable();
case "rotate":
return new RotateDrawable();
case "animated-rotate":
return new AnimatedRotateDrawable();
case "animation-list":
return new AnimationDrawable();
case "inset":
return new InsetDrawable();
case "bitmap":
return new BitmapDrawable();
case "nine-patch":
return new NinePatchDrawable();
default:
return null;
}
}
最后,对xml的解析通过drawable.inflate(mRes, parser, attrs, theme);
交给了具体的drawable实现类来处理。