TypedArray a = obtainStyledAttributes(R.styleable.Gallery);
Log.i(TAG,"a " + a + " -> \n" + a.getIndexCount() + " \n" + a.length() + " \n" + R.styleable.Gallery.length);
mGalleryItemBackground = a.getResourceId( R.styleable.Gallery_android_galleryItemBackground, 0);
Log.i(TAG,"mGalleryItemBackground " + mGalleryItemBackground);
a.recycle();
附:
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Gallery">
<attr name="android:galleryItemBackground" />
</declare-styleable>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Gallery">
<attr name="android:galleryItemBackground" />
<attr name="galleryItemBackground" format="reference" />
<attr name="backgroundDimEnabled" format="boolean" />
</declare-styleable>
</resources>
1.TypedArray a = obtainStyledAttributes(R.styleable.Gallery);
Retrieve styled attribute information in this Context's theme。
从当前的上下文theme中返回styled的属性值。
那到底是什么意思呢?
进入Context.java
public final TypedArray obtainStyledAttributes(
int[] attrs) {
return getTheme().obtainStyledAttributes(attrs); -----1
}
先看 getTheme()
public abstract Resources.Theme getTheme();
在ContextImp.java实现getTheme()
@Override
public Resources.Theme getTheme() {
if (mTheme == null) {
mThemeResource = Resources.selectDefaultTheme(mThemeResource,
getOuterContext().getApplicationInfo().targetSdkVersion); ----2
mTheme = mResources.newTheme(); ---3
mTheme.applyStyle(mThemeResource, true); ---4
}
return mTheme;
}
大概看下2
Resources.java
public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
return selectSystemTheme(curTheme, targetSdkVersion,
com.android.internal.R.style.Theme,
com.android.internal.R.style.Theme_Holo,
com.android.internal.R.style.Theme_DeviceDefault);
}
此时的curTheme=0;targetSdkVersion=10
public static int selectSystemTheme(int curTheme, int targetSdkVersion,
int orig, int holo, int deviceDefault) {
if (curTheme != 0) {
return curTheme;
}
if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
return orig;
}
if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return holo;
}
return deviceDefault;
}
根据上面的数据,返回orig,即com.android.internal.R.style.Theme
看3,mTheme = mResources.newTheme();
mResources在init就有值,所以不会有空指针问题。
public final Theme newTheme() {
return new Theme();
}
简单理解就是为了实例化mTheme,不深入了。
看4,mTheme.applyStyle(mThemeResource, true);
即为mTheme.applyStyle(com.android.internal.R.style.Theme, true);
public void applyStyle(int resid, boolean force) {
AssetManager.applyThemeStyle(mTheme, resid, force);
}
哦,又多了一个mTheme,其实这个是刚才不深入的地方,还是简单进入看下
private final int mTheme;
Theme() {
mAssets = Resources.this.mAssets;
mTheme = mAssets.createTheme();
}
权当mTheme有值了。再下去就涉及JNI了。
不过AssetManager的applyThemeStyle这个函数也是在底层实现的。
android_util_AssetManager.cpp
简单看:
{ "applyThemeStyle", "(IIZ)V",(void*) android_content_AssetManager_applyThemeStyle },
static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
jint themeInt,
jint styleRes,
jboolean force)
{
ResTable::Theme* theme = (ResTable::Theme*)themeInt;
theme->applyStyle(styleRes, force ? true : false);
}
上面那个pplyStyle函数就不看了(c++部分薄弱)
回到1:obtainStyledAttributes(attrs)
public TypedArray obtainStyledAttributes(int[] attrs) {
int len = attrs.length;
TypedArray array = getCachedStyledAttributes(len);
array.mRsrcs = attrs;
AssetManager.applyStyle(mTheme, 0, 0, 0, attrs,
array.mData, array.mIndices);
return array;
}
private TypedArray getCachedStyledAttributes(int len) {
return new TypedArray(this,
new int[len*AssetManager.STYLE_NUM_ENTRIES],
new int[1+len], len);
}
返回一个TypedArray
算一算这个Array的大小:len=1;AssetManager.STYLE_NUM_ENTRIES=6;
new int[6],new int[2],1
还是没能把TypedArray形象化,就是知道它是包含数据的容器。目前就就此记录下,备后续再看。