Android Is it possible to define a map in an XML f

2019-01-22 13:13发布

问题:

I was trying to define a static hash table that makes use of resources, but I got stonewalled by the impossibility of accessing resources statically.

Then I realized that the best of all places to define a static map is in the resources files themselves.

How can I define a map in XML? I believe that if possible it should be similar to the Listpreference mechanism, with entries and entries-values.

回答1:

How can I define a map in XML?

<thisIsMyMap>
  <entry key="foo">bar</entry>
  <entry key="goo">baz</entry>
  <!-- as many more as your heart desires -->
</thisIsMyMap>

Put this in res/xml/, and load it using getResources().getXml(). Walk the events to build up a HashMap<String, String>.



回答2:

A simpler option would be to use two arrays. This has the benefit of not iterating the xml file again, uses less code and its more straight forward to use arrays of different types.

<string-array name="myvariablename_keys">
   <item>key1</item>
   <item>key1</item>
</string-array>

<string-array name="myvariablename_values">
   <item>value1</item>
   <item>value2</item>
</string-array>

Then your java code would look like this:

String[] keys = this.getResources().getStringArray(R.array.myvariablename_keys);
String[] values = this.getResources().getStringArray(R.array.myvariablename_values);
LinkedHashMap<String,String> map = new LinkedHashMap<String,String>();
for (int i = 0; i < Math.min(keys.length, values.length); ++i) {
   map.put(keys[i], values[i]);
}


回答3:

You can always embed json inside your strings.xml file:

res/values/strings.xml

<string name="my_map">{"F":"FOO","B":"BAR"}</string>

And inside your activity, you can build your map in the onStart method:

private HashMap<String, String> myMap;

@Override
protected void onStart() {
    super.onStart();
    myMap = new Gson().fromJson(getString(R.string.my_map), new TypeToken<HashMap<String, String>>(){}.getType());
}

This code needs the google-gson api to work, you can do it using the built in json api in the android sdk.

And As for accessing the Map statically you can create a static method:

private static HashMap<String, String> method(Context context) {
    HashMap<String, String> myMap = new Gson().fromJson(context.getString(R.string.serve_times), new TypeToken<HashMap<String, String>>(){}.getType());
    retrun myMap;
}


回答4:

The correct answer was mentioned by CommonsWare above, but as XML-parsing is not so simple, as following a simple parser for this purpose:

public static Map<String, String> getHashMapResource(Context context, int hashMapResId) {
    Map<String, String> map = new HashMap<>();
    XmlResourceParser parser = context.getResources().getXml(hashMapResId);

    String key = null, value = null;

    try {
        int eventType = parser.getEventType();

        while (eventType != XmlPullParser.END_DOCUMENT) {
            if (eventType == XmlPullParser.START_TAG) {
                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;
}