我正在创建一个应用程序,其中Web服务从Web服务(I.e BEL,FRA,SWE)中获取(以及其他)一堆代码。在运行时,我想将这些代码翻译成他们的apporiate名称,以显示给用户(即比利时,法国,瑞典)。可能有很多这些代码,所以我想知道是否有任何合适的方式将(代码,名称)条目存储为Android中的XML资源中的某种地图,因此我可以快速获取名称给定的代码?
这是关于速度的全部,因为地图可以有几百个条目。
答案 0 :(得分:40)
今天我遇到了同样的问题并且长时间研究developer.android.com没有帮助,因为Android资源不能是哈希(地图),只有数组。
所以我发现了两种方式:
拥有像“BEL | Belgium”这样的字符串数组,在程序的早期解析这些字符串并存储在Map<>
有2个字符串数组:首先是“BEL”,“FRA”,“SWE”,第二个是“比利时”,“法国”,“瑞典”。
第二个更敏感,因为您必须同时同步两个数组中的更改和顺序。
答案 1 :(得分:39)
我发现弗拉基米尔的answer非常引人注目,所以我实施了他的第一个建议:
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;
}
使用它是直截了当的。在您的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>
并在您的实施中:
SparseArray<String> myStringArray = parseStringArray(R.array.my_string_array);
答案 2 :(得分:37)
您还可以使用XML定义地图,将其放在res / xml中并解析为HashMap(suggested in this post)。如果要保持键盘顺序解析为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>
资源解析器:
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;
}
}
答案 3 :(得分:8)
我有类似的要求,我以比现有解决方案更强大的方式解决了这个问题。
首先创建一个国家/地区数组数组:
<array name="countries_array_of_arrays">
<item>@array/es</item>
<item>@array/it</item>
</array>
然后为每个国家/地区添加一个包含国家/地区信息的数组:
<array name="es">
<item>ES</item>
<item>ESPAÑA</item>
</array>
<array name="it">
<item>IT</item>
<item>ITALIA</item>
</array>
一些注意事项:
每个国家/地区数组中的name
值(es,it)必须与countries_array_of_arrays
中的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();
值匹配(如果不是,则会收到错误)。
对于所有阵列,每个阵列上的项目顺序必须相同。因此,请始终将国家/地区代码放在第一位,将国家/地区名称放在第二位。
每个国家/地区可以包含任意数量的字符串,而不仅仅是国家/地区代码和名称。
要在代码上加载字符串,请执行以下操作:
List
我将资源加载到2 Map
,但您可以根据需要使用@drawable
。
为什么这会更强大?
它允许您使用字符串资源,从而翻译不同语言的国家/地区名称。
它允许您将任何类型的资源关联到每个国家/地区,而不仅仅是字符串。例如,您可以将<string-array>
与国家/地区或包含该国家/地区/州的<array name="it">
<item>IT</item>
<item>ITALIA</item>
<item>@drawable/flag_italy</item>
<item>@array/provinces_italy</item>
</array>
相关联。
高级示例:
countryTypedArray.getDrawable(2)
请注意,我还没有尝试过,但我已经在other questions看过了。在这种情况下,您可以使用<string-array
来获取drawable,例如。
<强>简化:强>
如果您只使用国家/地区数组的字符串,则可以使用<array>
(而不是<string-array name="it">
<item>IT</item>
<item>ITALIA</item>
</string-array>
),如下所示:
String[]
您可以直接获取TypedArray
代替String[] countryArray = getResources().getStringArray(id);
countryCodes.add(countryArray[0]);
countryNames.add(countryArray[1]);
来简化for循环代码:
<string-array>
关于有2 <string-array>
:
最初我想在另一个答案中提到2个<string-array>
(一个用于国家代码,另一个用于国家/地区名称)。但是,使用2 // extension.js
// for now, hardcode limit of 5 for testing purposes
function getAllSessions(callback) {
chrome.sessions.getRecentlyClosed({maxResults: 5}, function(sessions) {
callback(sessions);
});
}
document.addEventListener('DOMContentLoaded', function() {
getAllSessions(function(sessions) {
console.debug(sessions)
});
});
时,您必须确保商品的数量和顺序匹配。有了这个解决方案,你就不用了。在这方面它更安全。请注意,正如我所说,每个国家/地区阵列上的项目顺序都很重要:始终将国家/地区代码和国家/地区名称放在同一顺序中!
答案 4 :(得分:3)
对你来说可能会迟到,但对于其他感兴趣的人来说。 如果您的3位数国家/地区代码是有效的ISO 3166-1 alpha-3代码
Locale locale = new Locale("", "SWE");
String countryName = locale.getDisplayCountry();
这样可以使用正确的语言提供完整的国家/地区名称。
答案 5 :(得分:3)
我认为最安全,最干净的方法尚未发布,所以这是我的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;
}
}
然后在strings.xml中:
<string name="france">France</string>
...
当您收到来自网络服务的项目时:
Country country = Country.valueOf(countryCodeFromServer);
context.getResources().getString(country.stringResId);
构建时间检查将确保每个国家/地区都有每个区域设置的资源,如果将列表维护为阵列资源,则不会拥有该资源。