If I have different resource names like elephant, tiger and cat. And I want to create a method accepting the resource name and return the drawable object. Then I wrote this
public Drawable getDrawable(String name){
int defaultResId= ResourceOptimizer.getResId(name,R.drawable.class);
return getResources().getDrawable(defaultResId);
}
which the ResourceOptimizer
is
public class ResourceOptimizer {
public static int getResId(String resName, Class<?> c) {
try {
Field idField = c.getDeclaredField(resName);
return idField.getInt(idField);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
}
But the problem is that getResources()
needs to be called
in an activity or fragment, otherwise you to pass the context.
Passing the context might cause memory leak. Especially, when
it has to be passed through several classes. I’m wondering if
there is some way to get the resource by a better convenient way.
like
R.id.DRAWABLE_NAME
which the ResourceOptimizer is
Resources
already has a getIdentifier()
method.
But the problem is that getResources() needs to be called in an activity or fragment, otherwise you to pass the context.
Correct. Resources are only available by means of a suitable Context
. Note that "suitable" depends on circumstances; for UIs, you almost always want to use the Context
from your activity or fragment. For example, you might want different drawables based on whether the device is in dark mode or not on Android 10+.
Passing the context might cause memory leak
Not with the code that you have here, as you are not saving the Context
, or anything from it, in a field that might outlive the Context
itself.
I’m wondering if there is some way to get the resource by a better convenient way. like R.id.DRAWABLE_NAME
getDrawable()
is a method on Context
. So, call getDrawable(R.drawable.elephant)
.
Your code is trying specifically to avoid using R.drawable
, instead using the String
name. So, this turns into:
getDrawable(getResources().getIdentifier(yourString, "drawable", getPackageName()))
where yourString
is the string basename of your resource (e.g., "elephant"
).
Ideally, you would cache the value returned by getIdentifier()
, if you expect to retrieve the same resource by this code many times within the life of your process. Reflection is not cheap.