从XML资源创建hashmap/map

Kim*_*afr 44 xml android

我正在创建一个应用程序,其中Web服务从Web服务(即BEL,FRA,SWE)获取(以及其他)一堆代码.在运行期间,我想将这些代码翻译成他们的apporiate名称,以显示给用户(即比利时,法国,瑞典).可能有很多这些代码,所以我想知道是否有任何合适的方式将(代码,名称)条目存储为Android中的XML资源中的某种地图,因此我可以快速获取名称给定的代码?

这都是关于速度的,因为地图可以有几百个条目.

Vla*_*mir 41

今天我遇到了同样的问题并且长时间研究developer.android.com没有帮助,因为Android资源不能是哈希(地图),只有数组.

所以我找到了两种方法:

  1. 有一个像"BEL | Belgium"这样的字符串数组,在程序的早期解析这些字符串并存储在Map <>中

  2. 有2个字符串数组:首先是"BEL","FRA","SWE"的值,第二个是"Belgium","France","Sweden".

其次是更敏感,因为您必须同时同步两个数组中的更改和顺序.

  • 或者,您可以将json对象存储在资源中并将其解析为Map (6认同)
  • 真可悲... Android绝对应该涵盖这种方法或`beans.xml`方法... (2认同)
  • 使用第二种方法并通过测试强制执行同步。 (2认同)

Jen*_*ohl 41

我发现弗拉基米尔的答案非常引人注目,所以我实施了他的第一个建议:

public SparseArray<String> parseStringArray(int stringArrayResourceId) {
    String[] stringArray = getResources().getStringArray(stringArrayResourceId);
    SparseArray<String> outputArray = new SparseArray<String>(stringArray.length);
    for (String entry : stringArray) {
        String[] splitResult = entry.split("\\|", 2);
        outputArray.put(Integer.valueOf(splitResult[0]), splitResult[1]);
    }
    return outputArray;
}
Run Code Online (Sandbox Code Playgroud)

使用它是直截了当的.在你strings.xml你有一个string-array像这样:

<string-array name="my_string_array">
    <item>0|Item 1</item>
    <item>1|Item 4</item>
    <item>2|Item 3</item>
    <item>3|Item 42</item>
    <item>4|Item 17</item>
</string-array>
Run Code Online (Sandbox Code Playgroud)

并在您的实施中:

SparseArray<String> myStringArray = parseStringArray(R.array.my_string_array);
Run Code Online (Sandbox Code Playgroud)


vok*_*lam 38

您还可以使用XML定义映射,将其放在res/xml中并解析为HashMap(本文中建议).如果要保持键盘顺序解析为LinkedHashMap.简单实现如下:

地图资源res/xml:

<?xml version="1.0" encoding="utf-8"?>
<map linked="true">
    <entry key="key1">value1</entry>
    <entry key="key2">value2</entry>
    <entry key="key3">value3</entry>
</map>
Run Code Online (Sandbox Code Playgroud)

资源解析器:

public class ResourceUtils {
    public static Map<String,String> getHashMapResource(Context c, int hashMapResId) {
        Map<String,String> map = null;
        XmlResourceParser parser = c.getResources().getXml(hashMapResId);

        String 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.getAttributeBooleanValue(null, "linked", false);

                        map = isLinked ? new LinkedHashMap<String, String>() : new HashMap<String, String>();
                    } else if (parser.getName().equals("entry")) {
                        key = parser.getAttributeValue(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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Alb*_*lvo 8

我有类似的要求,我以比当前解决方案更强大的方式解决了它.

首先创建一个国家/地区数组数组:

<array name="countries_array_of_arrays">
    <item>@array/es</item>
    <item>@array/it</item>
</array>
Run Code Online (Sandbox Code Playgroud)

然后为每个国家添加一个包含国家/地区信息的数组:

<array name="es">
    <item>ES</item>
    <item>ESPAÑA</item>
</array>
<array name="it">
    <item>IT</item>
    <item>ITALIA</item>
</array>
Run Code Online (Sandbox Code Playgroud)

一些说明:

  1. name每个国家/地区数组中的值(es,it)必须与中的数组匹配countries_array_of_arrays(如果没有,则会收到错误).

  2. 对于所有阵列,每个阵列上的项目顺序必须相同.因此,总是将国家/地区代码放在第一位,将国家/地区名称放在第二位.

  3. 每个国家/地区可以包含任意数量的字符串,而不仅仅是国家/地区代码和名称.

要在代码上加载字符串,请执行以下操作:

TypedArray countriesArrayOfArrays = getResources().obtainTypedArray(R.array.countries_array_of_arrays);
int size = countriesArrayOfArrays.length();
List<String> countryCodes = new ArrayList<>(size);
List<String> 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();
Run Code Online (Sandbox Code Playgroud)

在这里我将资源加载到2,ListMap如果你愿意,你可以使用a .

为什么这更强大?

  1. 它允许您使用字符串资源,从而翻译不同语言的国家/地区名称.

  2. 它允许您将任何类型的资源关联到每个国家/地区,而不仅仅是字符串.例如,您可以将a @drawable与国家<string-array>/ 地区标志或包含该国家/地区的省/州相关联.

高级示例:

<array name="it">
    <item>IT</item>
    <item>ITALIA</item>
    <item>@drawable/flag_italy</item>
    <item>@array/provinces_italy</item>
</array>
Run Code Online (Sandbox Code Playgroud)

请注意,我没有尝试过,但我已经在其他问题中看到了它.例如,在这种情况下,您将使用countryTypedArray.getDrawable(2)获取drawable.

简化:

如果您只使用国家/地区数组的字符串,您可以使用<string-array(而不是<array>)这样的:

<string-array name="it">
    <item>IT</item>
    <item>ITALIA</item>
</string-array>
Run Code Online (Sandbox Code Playgroud)

您可以通过直接获取String[]而不是以下内容来简化for循环代码TypedArray:

String[] countryArray = getResources().getStringArray(id);
countryCodes.add(countryArray[0]);
countryNames.add(countryArray[1]);
Run Code Online (Sandbox Code Playgroud)

有关2的说明<string-array>:

最初我想到的是<string-array>另一个答案中提到的2 (一个用于国家代码,另一个用于国家名称).但是,使用2时,<string-array>您必须确保项目的数量顺序匹配.有了这个解决方案,你就不会.在这方面它更安全.请注意,正如我所说,每个国家/地区阵列上的项目顺序很重要:始终将国家/地区代码和国家/地区名称放在同一顺序中!

  • TLDR:数组数组,不错! (2认同)

Joh*_*y C 5

我认为最安全、最干净的方法还没有发布,所以这是我的 0.02 美元:

如何在代码中创建一个引用字符串资源 id 作为其显示值的枚举类型:

public enum Country {
   FRA(R.string.france),
   BEL(R.string.belgium),
   SWE(R.string.sweden),
   ...;

   @StringRes public int stringResId;

   Country(@StringRes id stringResId) {
       this.stringResId = stringResId;
   }
} 
Run Code Online (Sandbox Code Playgroud)

然后在 strings.xml 中:

<string name="france">France</string>
...
Run Code Online (Sandbox Code Playgroud)

当您从网络服务收到商品时:

Country country = Country.valueOf(countryCodeFromServer);
context.getResources().getString(country.stringResId);
Run Code Online (Sandbox Code Playgroud)

构建时检查将确保每个国家/地区都有针对每个区域设置的资源,如果将列表维护为数组资源,则不会拥有该资源。