Search code examples
androidandroid-resources

How to link android resource values together?


I have trouble finding a pattern to create constants that point to a collection of resource values. Let's say I have four TextViews, in each corner of the layout. I then have four different sets of constant content to randomly assign to these four TextViews. That content comes with a text and a background color for the TextView. Those values are defined in the strings.xml and colors.xml. Let's say the strings.xml looks like this:

<resources>
    <string name="A">Text for A</string>
    <string name="B">Text for B</string>
    <string name="C">Text for C</string>
    <string name="D">Text for D</string>
</resources>

and my colors.xml like this:

<resources>
    <color name="A">#AAAAAA</color>
    <color name="B">#BBBBBB</color>
    <color name="C">#CCCCCC</color>
    <color name="D">#DDDDDD</color>
</resources>

In the Activity class I then want to write a method to assign these values randomly to the TextViews. I could do this by creating lists for each type of value, then picking a random TextView out of these four, remove the first value out of each list and assign it to the TextView:

List<Integer> colors = Arrays.asList(R.color.A,
                                     R.color.B,
                                     R.color.C,
                                     R.color.D);
List<String> strings = Arrays.asList(R.string.A,
                                     R.string.B,
                                     R.string.C,
                                     R.string.D);

for (int i = 4; i > 0; i--) {
    int randomNumber = // get a random number between 0 and i
    TextView tv = // get text view based on i (by switch case)
    tv.setText(string.remove(0));
    tv.setBackgroundColor(getResources().getColor(colors.remove(0));
}

This solution doesn't seem good to me because the relationship between the string and the color values is not obvious at first sight. Also it is a lot of code to write. I then thought of an enum, where each enum-value has a reference to its associated resources.

enum TextViewContent {
    A(R.string.A, R.color.A),
    B(R.string.B, R.color.B),
    C(R.string.C, R.color.C),
    D(R.string.D, R.color.D);

    public final String string;
    public final int color;

    private TextViewContent(String string, int color) {
        this.string = string;
        this.color = color;
    }
}

This solution looked fine to me until I saw this page https://android.jlelse.eu/android-performance-avoid-using-enum-on-android-326be0794dc3 where they recommend to avoid using enums in android code. In the examples of that page the enums to avoid were all replacable by a set of constants of a primitive type. I am not sure if using an enum is still a good idea. On the other hand I am running out of ideas how to solve this problem.
Is the use of an enum the best solution in this case? If not: What is the best solution here?


Solution

  • Prepare your resources in such a way that can be used as arrays:

    <string-array name="texts">
        <item>Text for A</item>
        <item>Text for B</item>
        <item>Text for C</item>
        <item>Text for D</item>
    </string-array>
    
    <color name="A">#AAAAAA</color>
    <color name="B">#BBBBBB</color>
    <color name="C">#CCCCCC</color>
    <color name="D">#DDDDDD</color>
    
    <integer-array name="colors">
        <item>@color/A</item>
        <item>@color/B</item>
        <item>@color/C</item>
        <item>@color/D</item>
    </integer-array>
    

    Then all you have to do to retrieve them is:

        String[] strings = getResources().getStringArray(R.array.texts);
        int[] colors = getResources().getIntArray(R.array.colors);
    

    It is not a lot of coding.
    It also is easy to maintain because if you want to change the texts or colors, or to add new items, or delete items you only have to work in the resources.
    As for the relationship between the string and the color values it's more than obvious.