先来看一段在XML中配置的代码
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="100dp"
android:maxHeight="100dp"
android:orientation="vertical"
android:src="@drawable/ic_launcher_background"
android:tintMode="screen" />
如何通过解析配置中的属性,来完成对象的数据初始化。
比如从android:maxHeight
到setMaxHeight
先来看一下ImageView
构造函数。
public ImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
saveAttributeDataForStyleable(context, R.styleable.ImageView,
attrs, a, defStyleAttr, defStyleRes);
...
setMaxWidth(a.getDimensionPixelSize(R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
setMaxHeight(a.getDimensionPixelSize(R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
...
a.recycle();
}
setMaxHeight(a.getDimensionPixelSize(R.styleable.ImageView_maxHeight, Integer.
MAX_VALUE
));
通过TypeArray
通过R.styleable.ImageView_maxHeight
这个Id
来读取数据。
public int getDimensionPixelSize(@StyleableRes int index, int defValue) {
final int attrIndex = index;
index *= STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index + STYLE_TYPE];
if (type == TypedValue.TYPE_NULL) {
return defValue;
} else if (type == TypedValue.TYPE_DIMENSION) {
return TypedValue.complexToDimensionPixelSize(data[index + STYLE_DATA], mMetrics);
} else if (type == TypedValue.TYPE_ATTRIBUTE) {
final TypedValue value = mValue;
getValueAt(index, value);
}
}
- 巧妙的数据结构
mData
是一个数组,存储了解析后的属性数据信息,它主要由多组数据组成,每组数据都是一样的结构。
[TYPE, DATA, ASSET_COOKIE, RESOURCE_ID, CHANGING_CONFIGURATIONS, DENSITY,SOURCE_RESOURCE_ID,TYPE, DATA, ASSET_COOKIE, RESOURCE_ID, CHANGING_CONFIGURATIONS, DENSITY,SOURCE_RESOURCE_ID,TYPE, DATA, ASSET_COOKIE, RESOURCE_ID, CHANGING_CONFIGURATIONS, DENSITY,SOURCE_RESOURCE_ID]
以上就是Data
的数据结构,你可以理解成间隔7
个数就是一个组。假如要获取第三组数据,那就是
index=3
,要是获取第三组数据中的
TYPE
,那就是index*7+0
;
DATA
,那就是index*7+1
;
DENSITY
,那就是index*7+5
。
所以只需要知道Index
,就可以知道每一个属性的7
中数据信息了。关于这7种数据信息的偏移量,源代码中把他们定义成了7个常量。
static final int STYLE_NUM_ENTRIES = 7;
static final int STYLE_TYPE = 0;
static final int STYLE_DATA = 1;
static final int STYLE_ASSET_COOKIE = 2;
static final int STYLE_RESOURCE_ID = 3;
static final int STYLE_CHANGING_CONFIGURATIONS = 4;
static final int STYLE_DENSITY = 5;
static final int STYLE_SOURCE_RESOURCE_ID = 6;
理解完数据结构之后,再回头来看一下,获取dimen
的代码,就比较容易理解了。
final int attrIndex = index;
index *= STYLE_NUM_ENTRIES;//算该组开始索引
final int[] data = mData;
final int type = data[index + STYLE_TYPE];//根据偏移量获取数据