Dynamically Retrieving Resources in Android

Normally, when retrieving resources (drawables, strings, what have you) in code you use the automatically generated R.java to do so. However, I recently wrote a reference application wherein each item in a ListView has a different icon next to it. The data for all this is stored in JSON as an asset, which meant that there was no way for me to link my data to R.java.

Still, I needed some way to get a hold of the Drawable by name, and so I first turned to Resources.getIdentifier(). This method does the job well of finding the resource id of anything you desire, in any package:

Resources r = getResources();
int drawableId = r.getIdentifier("drawableName", "drawable", "com.mypackage.myapp");

This is all well and good, but: getIdentifier() is a general tool and as a result, slow. Running through 10,000 iterations, it took about 3200 ms on my G1. Also, it requires that you pass around a Context (or a Resources) wherever you need to use getIdentifier() which is an annoyance and seems unnecessary given that you can access R.java just fine normally in code.

The better solution - as long as you are retrieving data from your application's own R.java - is to use reflection.

try {
    Class res = R.drawable.class;
    Field field = res.getField("drawableName");
    int drawableId = field.getInt(null);
catch (Exception e) {
    Log.e("MyTag", "Failure to get drawable id.", e);

In testing, the second method is about 5x faster than getIdentifier(). Not only that, but it means you don't have to pass a Resources object around to use it. Obviously this cannot be used if you're accessing resources outside of your application's permissions and you'll have to rely on getIdentifier() then.

One last note - simply linking to R.java is way faster than either of these two methods, so only fall back on these if you need to link to resource identifiers dynamically by name.

comments powered by Disqus