Platform Resource Aliases
One of the reasons why I keep close tabs on Stack Overflow is that, every now and then, I’m reminded of a technique that I should be promoting more.
Today’s example of this comes from this question,
where a developer inheriting an existing Android Studio project questioned
why the project had a res/values/drawables.xml
file that contains
a bunch of <item>
elements:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item name="ic_menu_camera" type="drawable">@android:drawable/ic_menu_camera</item>
<item name="ic_menu_gallery" type="drawable">@android:drawable/ic_menu_gallery</item>
<item name="ic_menu_slideshow" type="drawable">@android:drawable/ic_menu_slideshow</item>
<item name="ic_menu_manage" type="drawable">@android:drawable/ic_menu_manage</item>
<item name="ic_menu_share" type="drawable">@android:drawable/ic_menu_share</item>
<item name="ic_menu_send" type="drawable">@android:drawable/ic_menu_send</item>
</resources>
What the original developer did was set up project aliases for platform resources.
There are lots of resources available in the Android SDK. You are welcome to
refer to them directly if you want, such as @android:string/ok
or
android.R.color.black
.
However, platform resources have two key problems:
-
They tend to be very specific.
android.R.color.black
is a color resource that resolves to black. It should always be black. -
They might vary by Android version or even device manufacturer build. Some manufacturer, or even Google itself, might decide that orange is the new black and have
android.R.color.black
resolve to some shade of orange.
Ideally, you add a bit of indirection here, so that all of your Java code and other resources that today might use platform resources could switch tomorrow to some other implementation of those resources, without having to change all of the references to the resources.
Sometimes, we do this via styles and themes. However, that gets confusing, can be overkill, and does not necessarily cover all scenarios.
Resource aliases are another approach, the one taken by the original developer
of the code from the Stack Overflow question. <item>
elements, with
type
pointing to the type of resource, gives us indirection. With the
above XML in a project, the project code and other resources can refer
to R.drawable.ic_menu_share
and such. Right now, the implementations of
those drawables happen to be platform resources, by means of the <item>
elements. However, later on, you could get rid of the <item>
elements and
add custom drawables as replacements. Nothing that refers to the resource
needs to change, courtesy of the indirection.
Even in cases where you do not think that you will need to switch to a
custom resource, using this sort of indirection technique lets you
use logical resource names (e.g., R.color.divider
instead of
android.R.color.black
, to make it easier for you to switch to
android.R.color.holo_orange_dark
later on without other code changes).
Again, styles and themes may supplant the need
for a lot of these aliases, but not everything belongs in a style resource.
Want an expert opinion on your Android app architecture decisions? Perhaps Mark Murphy can help!
Tweet