Créer un hashmap / map à partir de ressources XML

Je fais une application où un service Web récupère (entre autres) un tas de codes à partir d’un service Web (par exemple, BEL, FRA, SWE). Pendant l’exécution, je veux traduire ces codes en leurs noms respectifs pour les afficher aux utilisateurs (c’est-à-dire en Belgique, en France et en Suède). Il peut y avoir beaucoup de ces codes, alors je me demande s’il existe un moyen approprié de stocker l’entrée (code, nom) comme une sorte de carte dans les ressources XML d’Android, pour que je puisse récupérer rapidement le nom par le code donné?

Tout est question de vitesse ici, puisque la carte peut contenir quelques centaines d’entrées.

Aujourd’hui, j’ai rencontré le même problème et étudier developer.android.com pendant longtemps ne m’a pas aidé car les ressources Android ne peuvent pas être des hachages (cartes), mais uniquement des tableaux.

J’ai donc trouvé 2 façons:

  1. Avoir un tableau de chaînes de valeurs comme “BEL | Belgium”, parsingr ces chaînes au début du programme et les stocker dans une carte <>

  2. Avoir 2 tableaux: d’abord avec les valeurs de “BEL”, “FRA”, “SWE” et ensuite avec “Belgium”, “France”, “Sweden”.

La seconde est plus sensible car vous devez synchroniser les modifications et l’ordre dans les deux baies simultanément.

J’ai trouvé la réponse de Vladimir assez convaincante alors j’ai mis en œuvre sa première suggestion:

 public SparseArray parseSsortingngArray(int ssortingngArrayResourceId) { Ssortingng[] ssortingngArray = getResources().getSsortingngArray(ssortingngArrayResourceId); SparseArray outputArray = new SparseArray(ssortingngArray.length); for (Ssortingng entry : ssortingngArray) { Ssortingng[] splitResult = entry.split("\\|", 2); outputArray.put(Integer.valueOf(splitResult[0]), splitResult[1]); } return outputArray; } 

L’utiliser est simple. Dans votre ssortingngs.xml vous avez un ssortingng-array comme ceci:

  0|Item 1 1|Item 4 2|Item 3 3|Item 42 4|Item 17  

et dans votre implémentation:

 SparseArray mySsortingngArray = parseSsortingngArray(R.array.my_ssortingng_array); 

Vous pouvez également définir une carte en XML, la placer dans res / xml et parsingr dans HashMap ( suggéré dans cet article ). Si vous souhaitez conserver l’ordre d’parsing des clés dans LinkedHashMap. La mise en œuvre simple suit:

Ressource cartographique dans res/xml :

   value1 value2 value3  

Analyseur de ressources:

 public class ResourceUtils { public static Map getHashMapResource(Context c, int hashMapResId) { Map map = null; XmlResourceParser parser = c.getResources().getXml(hashMapResId); Ssortingng key = null, value = null; try { int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_DOCUMENT) { Log.d("utils","Start document"); } else if (eventType == XmlPullParser.START_TAG) { if (parser.getName().equals("map")) { boolean isLinked = parser.getAtsortingbuteBooleanValue(null, "linked", false); map = isLinked ? new LinkedHashMap() : new HashMap(); } else if (parser.getName().equals("entry")) { key = parser.getAtsortingbuteValue(null, "key"); if (null == key) { parser.close(); return null; } } } else if (eventType == XmlPullParser.END_TAG) { if (parser.getName().equals("entry")) { map.put(key, value); key = null; value = null; } } else if (eventType == XmlPullParser.TEXT) { if (null != key) { value = parser.getText(); } } eventType = parser.next(); } } catch (Exception e) { e.printStackTrace(); return null; } return map; } } 

J’avais une exigence similaire et je l’ai résolue d’une manière plus puissante que les solutions actuelles.

Créez d’abord une ressource qui est un tableau de tableaux de pays:

  @array/es @array/it  

Ensuite, pour chaque pays, ajoutez un tableau avec les informations sur le pays:

  ES ESPAÑA   IT ITALIA  

Quelques notes:

  1. Les valeurs de name (es, it) sur chaque tableau de pays doivent correspondre à celles de counsortinges_array_of_arrays (vous obtiendrez une erreur si ce n’est pas le cas).

  2. L’ordre des éléments sur chaque tableau doit être le même pour tous les tableaux. Donc, mettez toujours le code du pays en premier et le nom du pays en second, par exemple.

  3. Vous pouvez avoir n’importe quel nombre de chaînes pour chaque pays, pas seulement le code du pays et le nom.

Pour charger les chaînes sur votre code, procédez comme suit:

 TypedArray counsortingesArrayOfArrays = getResources().obtainTypedArray(R.array.counsortinges_array_of_arrays); int size = counsortingesArrayOfArrays.length(); List countryCodes = new ArrayList<>(size); List countryNames = new ArrayList<>(size); TypedArray countryTypedArray = null; for (int i = 0; i < size; i++) { int id = countriesArrayOfArrays.getResourceId(i, -1); if (id == -1) { throw new IllegalStateException("R.array.countries_array_of_arrays is not valid"); } countryTypedArray = getResources().obtainTypedArray(id); countryCodes.add(countryTypedArray.getString(0)); //noinspection ResourceType countryNames.add(countryTypedArray.getString(1)); } if (countryTypedArray != null) { countryTypedArray.recycle(); } countriesArrayOfArrays.recycle(); 

Ici, je charge les ressources sur 2 List mais vous pouvez utiliser une Map si vous le souhaitez.

Pourquoi est-ce plus puissant?

  1. Il vous permet d'utiliser des ressources de chaîne et donc de traduire les noms de pays pour différentes langues.

  2. Cela vous permet d' associer n'importe quel type de ressource à chaque pays, pas seulement des chaînes. Par exemple, vous pouvez associer un @drawable à un indicateur de pays ou à un qui contient des provinces / états pour le pays.

Exemple avancé:

  IT ITALIA @drawable/flag_italy @array/provinces_italy  

Notez que je n'ai pas essayé ceci mais je l'ai vu dans d' autres questions . Dans ce cas, vous utiliserez par exemple countryTypedArray.getDrawable countryTypedArray.getDrawable(2) pour obtenir le dessinable, par exemple.

Simplification:

Si vous utilisez uniquement des chaînes pour le tableau de pays, vous pouvez utiliser un (au lieu d'un ) comme ceci:

  IT ITALIA  

Et vous pouvez simplifier un peu le code for-loop en obtenant directement un Ssortingng[] au lieu d'un TypedArray :

 Ssortingng[] countryArray = getResources().getSsortingngArray(id); countryCodes.add(countryArray[0]); countryNames.add(countryArray[1]); 

Une note sur le fait d'avoir 2 :

Au départ, je pensais avoir 2 (un pour le code du pays et un autre pour le nom du pays) comme indiqué sur une autre réponse. Cependant, avec 2 vous devez vous assurer que le nombre et l' ordre des éléments correspondent. Avec cette solution, vous ne le faites pas. C'est plus sûr à cet égard. Notez que, comme je l'ai dit, l'ordre des articles sur chaque tableau de pays est important: mettez toujours le code du pays et le nom du pays dans le même ordre!

Il pourrait être en retard pour vous, mais pour toute autre personne intéressée. Si vos codes de pays à 3 chiffres sont des codes ISO 3166-1 alpha-3 valides

 Locale locale = new Locale("", "SWE"); Ssortingng countryName = locale.getDisplayCountry(); 

Cela donne le nom de pays complet avec la langue correcte.

Je pense que l’approche la plus sûre et la plus propre n’a pas encore été publiée, alors voici mes 0,02 $:

Que diriez-vous de créer un type enum dans le code qui référence l’ID de ressource de chaîne pour sa valeur d’affichage:

 public enum Country { FRA(R.ssortingng.france), BEL(R.ssortingng.belgium), SWE(R.ssortingng.sweden), ...; @SsortingngRes public int ssortingngResId; Country(@SsortingngRes id ssortingngResId) { this.ssortingngResId = ssortingngResId; } } 

Ensuite, dans ssortingngs.xml:

 France ... 

Et lorsque vous recevez un article du service Web:

 Country country = Country.valueOf(countryCodeFromServer); context.getResources().getSsortingng(country.ssortingngResId); 

Les vérifications de la durée de la construction garantissent que chaque pays dispose d’une ressource pour chaque environnement local, ce que vous n’auriez pas si vous gérez la liste en tant que ressource de tableau.