问题
I'm working with parsing custom attributes, and I've come across something weird. Let's say my parser looks something like this:
final TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.Item);
final int size = attributes.getIndexCount();
for(int i = 0; i < size; i++) {
final int attr = attributes.getIndex(i);
if(attr == R.styleable.Item_custom_attrib) {
final int resourceId = attributes.getResourceId(attr, -1);
if(resourceId == -1)
throw new Resources.NotFoundException("The resource specified was not found.");
...
}
attributes.recycle();
This works. Now, if I replace line #2 with final int size = attributes.length();
which means I get this:
final TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.Item);
final int size = attributes.length();
for(int i = 0; i < size; i++) {
final int attr = attributes.getIndex(i);
if(attr == R.styleable.Item_animation_src) {
final int resourceId = attributes.getResourceId(attr, -1);
if(resourceId == -1)
throw new Resources.NotFoundException("The resource specified was not found.");
...
}
attributes.recycle();
This crashes with the Resources.NotFoundException that I throw. In other words, attributes.getResourceId(attr, -1);
returns the default -1
value.
Now, in this particular case, there is only one custom attribute. Both attributes.getIndexCount()
and attributes.length()
return 1 because there is indeed a value in my attribute. Which means getIndex(i)
should return the same number, but it does not. It implies that getIndexCount()
does more than simply return the number of indices in the array that have data
. What exactly is the difference between the two methods where one allows me to get the attributes while the other does not?
回答1:
I was just fiddling with this and I found the whole thing confusing, but I think I got it figured out:
So you have declared N attributes in attrs.xml, for your class.
Now the size of the obtained TypedArray
is N. It always passes the same sized array.
But maybe you defined only X attributes in your layout xml, so getIndexCount()
returns X.
In your widget's init, if you were to ask yourself how many and which attributes
were defined in xml, you would first find out how many, using getIndexCount()
.
Then you loop from 0 to getIndexCount()-1
and ask the TypedArray
: "what's the index of
the i-th supplied attribute?".
So suppose you want to force an attribute to be set in xml, you can now check this because one of the calls to getIndex() has to return the id you are looking for.
But you can always ignore that, and supply default values. Then you can just call a.getInteger( R.styleable.MyClass_MyAttribute, defaultValue );
You can check R.java to see that all attribute IDs start at 0, for every class. The generated comments are also helpful to understand.
回答2:
you question is very simple indeed in common use,like this,first defines a class myview extends View{...},and then apply myview to layout.xml and define some attributes like 'textColor="#ffffffff"' etc,in the layout.xml,so your a.getIndexCount() return not null or not zero,that is what you expected.
now i change the question, you define a class myview extends Object,note not extends View class,and you will never use the layout.xml to your self-defined myview.the whole things like the android defined class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback, AccessibilityEventSource{...},no layout.xml,no extends View convenience,the only resources you can use is attrs.xml,styles.xml.
so what you able to do to let a.getIndexCount() return not null or not zero like mytop: why TypedArray.getIndexCount() always returns 0
来源:https://stackoverflow.com/questions/8405430/typedarray-and-styleable-attributes-getindexcount-vs-length