基于Android API 23源码,以 Window属性为例。
private int[] styleableWindow = new int[]{
android.R.attr.windowNoTitle,
android.R.attr.windowActionBar,
android.R.attr.windowActionBarOverlay,
android.R.attr.windowActionModeOverlay,
android.R.attr.windowSwipeToDismiss,
android.R.attr.windowContentTransitions,
android.R.attr.windowActivityTransitions
};
Activity样式如下:
<style name="appWindow" parent="Theme.AppCompat.Light">
<item name="android:windowActionBar">true</item>
<item name="android:windowNoTitle">true</item>
</style>
测试代码:
@SuppressWarnings("ResourceType")
private void outT(){
TypedArray a = this.obtainStyledAttributes(styleableWindow);
Log.e(Tag, "TypedArray长度 = "+ a.length()+"");
Log.e(Tag, a.toString());
Log.e(Tag, "FEATURE_NO_TITLE--- 1 = " + a.getBoolean(0, false));
Log.e(Tag, "FEATURE_ACTION_BAR--- 2 = " + a.getBoolean(1, false));
Log.e(Tag, "FEATURE_ACTION_BAR_OVERLAY--- 3 = " + a.getBoolean(2, false));
Log.e(Tag, "FEATURE_ACTION_MODE_OVERLAY--- 4 = " + a.getBoolean(3, false));
Log.e(Tag, "FEATURE_SWIPE_TO_DISMISS--- 5 = " + a.getBoolean(4, false));
Log.e(Tag, "FEATURE_CONTENT_TRANSITIONS--- 6 = " + a.getBoolean(5, false));
Log.e(Tag, "FEATURE_ACTIVITY_TRANSITIONS---7 = " + a.getBoolean(6, false));
a.recycle();
}
输出结果:
TypedArray长度 = 7;
数组内容整理后如下:
[
18, -1, 1, 0, 1073746944, 0,
18, -1, 1, 0, 1073746944, 0,
0 , 0, 1, 0, 0, 0,
18, 0, 1, 0, 1073746944, 0,
0 , 0, 1, 0, 0, 0,
18, 0, 1, 0, 1073746944, 0,
18, -1, 1, 0, 1073746944, 0
]
属性值输出:
FEATURE_NO_TITLE--- 1 = true
FEATURE_ACTION_BAR--- 2 = true
FEATURE_ACTION_BAR_OVERLAY--- 3 = false
FEATURE_ACTION_MODE_OVERLAY--- 4 = false
FEATURE_SWIPE_TO_DISMISS--- 5 = false
FEATURE_CONTENT_TRANSITIONS--- 6 = false
FEATURE_ACTIVITY_TRANSITIONS---7 = true
数据分析:
现在开始研究windowActionBar和windowNoTitle在TypedArray.mData数组中怎么表现的。
<item name="android:windowActionBar">true</item>
<item name="android:windowNoTitle">true</item>
查看TypedArray 创建代码:
static TypedArray obtain(Resources res, int len) {
final TypedArray attrs = res.mTypedArrayPool.acquire();
if (attrs != null) {
attrs.mLength = len;
attrs.mRecycled = false;
final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
if (attrs.mData.length >= fullLen) {
return attrs;
}
attrs.mData = new int[fullLen];
attrs.mIndices = new int[1 + len];
return attrs;
}
return new TypedArray(res,
new int[len*AssetManager.STYLE_NUM_ENTRIES],
new int[1+len], len);
}
TypedArray(Resources resources, int[] data, int[] indices, int len) {
mResources = resources;
mMetrics = mResources.mMetrics;
mAssets = mResources.mAssets;
mData = data;
mIndices = indices;
mLength = len;
}
发现,在不复用数组池的情况下,TypedArray.mData的长度 = styleable数组的长度 *AssetManager.STYLE_NUM_ENTRIES
即: styleable.length * 6
TypedArray.mData数组每6个数值表示一个属性。
测试代码中 styleableWindow [0] 表示windowNoTitle属性, styleableWindow [1] 表示windowActionBar属性.
在TypedArray.mData数组中使用下标0~5的数据表示windowNoTitle属性,6~11表示windowActionBar属性.
每6个数据中,
第0位数据表示AssetManager.STYLE_TYP—标识数据类型,0 表示 数据没有值。18 表示布尔类型,详见TypedValue
第1位数据表示 属性的值 AssetManager.STYLE_DATA
第2位数据表示 AssetManager.STYLE_ASSET_COOKIE
第3位数据表示 AssetManager.STYLE_RESOURCE_ID
第4位数据表示 AssetManager.STYLE_CHANGING_CONFIGURATIONS
第5位数据表示 AssetManager.STYLE_DENSITY
TypedArray.mData数组 0~5数据如下:
18, -1, 1, 0, 1073746944, 0,
mData[0] = 18 表示属性为布尔类型
mData[1] = -1 根据getBoolean源码return mData[0]!= 0 ;所以返回true
暂时分析到这里,剩下的部分,看看源码就都理解了。