La solution à laquelle j'ai abouti est celle suggérée par pskink dans comment: l'analyse du attrs.xml
et l'extraction des valeurs moi-même.
Il y a deux raisons qui l'ont parfaitement raisonnable de le faire de cette façon:
- Je en ai besoin pour un test de l'unité (en savoir un peu plus à ce sujet, lire ma conversation avec pskink dans les commentaires sous la question).
- Les paires nom/valeur ne sont stockées nulle part. Seuls
ints
sont utilisés lors de l'utilisation AttributeSet
.
Le code I fini avec est la suivante:
public final class AttrsUtils {
private static final String TAG_ATTR = "attr";
private static final String TAG_ENUM = "enum";
private static final String ATTRIBUTE_NAME = "name";
private static final String ATTRIBUTE_FORMAT = "format";
private static final String ATTRIBUTE_VALUE = "value";
@CheckResult
@NonNull
public static Map<String, Integer> getEnumAttributeValues(String attrName)
throws ParserConfigurationException, IOException, SAXException {
final File attrsFile = new File("../app/src/main/res/values/attrs.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(attrsFile);
doc.getDocumentElement().normalize();
Map<String, Integer> fontAttributes = new ArrayMap<>();
NodeList nList = doc.getElementsByTagName(TAG_ATTR);
for (int temp = 0; temp < nList.getLength(); temp++) {
Node attrNode = nList.item(temp);
if (attrNode.getNodeType() == Node.ELEMENT_NODE) {
Element attrElement = (Element) attrNode;
final String name = attrElement.getAttribute(ATTRIBUTE_NAME);
if (!attrElement.hasAttribute(ATTRIBUTE_FORMAT) || !name.equals(attrName)) {
continue;
}
final NodeList enumNodeList = attrElement.getElementsByTagName(TAG_ENUM);
for (int i = 0, size = enumNodeList.getLength(); i < size; ++i) {
final Node enumNode = enumNodeList.item(i);
if (enumNode.getNodeType() == Node.ELEMENT_NODE) {
Element enumElement = (Element) enumNode;
fontAttributes.put(
enumElement.getAttribute(ATTRIBUTE_NAME),
Integer.parseInt(enumElement.getAttribute(ATTRIBUTE_VALUE)));
}
}
break; // we already found the right attr, we can break the loop
}
}
return fontAttributes;
}
// Suppress default constructor for noninstantiability
private AttrsUtils() {
throw new AssertionError();
}
}
Cette méthode retourne un Map
de name
- value
paires qui représentent un attribut qui a attrName
.
Pour l'exemple je l'ai écrit dans la question, vous pouvez utiliser cette méthode comme ceci:
Map<String, Integer> enumAttr = AttrsUtils.getEnumAttributeValues("my_custom_enum");
que pensez-vous besoin? btw voir comment les enums std sont gérés dans le framework (typeface, visibility, scaleType etc) – pskink
@pskink J'en ai besoin pour un test unitaire. La valeur de ce type d'énumération est transmise à un module différent qui configure la vue. Je voulais écrire un test pour cet autre module, afin que je puisse être sûr que toutes les valeurs possibles sont prises en compte. –
donc vous avez correspondant 'enum' dans java rigth? Ensuite, appelez la méthode statique 'values ()' pour obtenir toutes les valeurs – pskink