Resource files host a very limited set of data types for Android developers. In a recent project, I wanted to have a mapped data set (in Java, the data type would have been Map<String, Map<String, Integer>>). I looked around the internet trying to find out how to do it, and the resounding answer was that it's not possible. Options include creating a <string-array> and an <integer-array>, and merging them into a Map at runtime, or alternatively creating a series of <string> resources, and merging them into a Map using reflection.
In my opinion, neither is a particularly good option for creating a resource, when the supported types work so seamlessly. So, I spent time developing a workaround. It turns our that the <array> type is functionally similar to Object[]. Each <item> can be any simple type (int, string, etc.), or else a reference to an existing resource (of any type). This means you can in fact have a nested array, you simply have to write each array separately and then use a reference in one to the other.
<resources>
<array name="my_array">
<item>@array/a0</item>
<item>@array/a1</item>
<item>@array/a2</item>
</array>
<array name="a0">
<item>0,0</item>
<item>0,1</item>
<item>0,2</item>
</array>
<array name="a1">
<item>1,0</item>
<item>1,1</item>
<item>1,2</item>
</array>
<array name="a2">
<item>2,0</item>
<item>2,1</item>
<item>2,2</item>
</array>
</resources>
Unfortunately, you can't simply load the resource as a Map or Object[][]. It's a little more complicated than that. You've got to load the TypedArray ('my_array'), loop through the values, obtain the resourceId for each of those values, use the resourceId to load the sub-array as another TypedArray, and then loop through those values. Further levels adds more steps of the same actions.
TypedArray myArray = getResources().obtainTypedArray(R.array.my_array);
int columns = myArray.length();
for(int i = 0; i < columns; i++)
{
int rowid = myArray.peekValue(i).resourceId;
TypedArray row = getResources().obtainTypedArray(rowid);
int values = row.length();
for(int k = 0; k < values; k++)
{
System.out.print(row.peekValue(i).coerceToString() + "\t");
}
System.out.println();
}
I have not tried creating array which reference each other, but it's definitely a bad idea. I suspect it'll result in a compile-time error, but I don't intend to try.
No comments:
Post a Comment