TypedArray and styleable attributes: getIndexCount() vs. length()

匆匆过客 提交于 2019-12-11 08:42:57

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!