Skip to main content

Android resources and runtime selection

Resources separate identity from representation​

Your code asks for a stable resource ID such as R.string.checkout_title. Android chooses the best representation for the current locale, night mode, density, API level, and other configuration.

Code asks for R.string.checkout_title
│
current configuration = Tamil + night + tablet
│
Android selects the best matching value

:::warning Android-only chapter The resource compiler, R, Resources, configuration, and manifest examples require an Android project. :::

Resource types​

res/
├─ values/ strings, colors, dimensions, styles
├─ layout/ View XML layouts
├─ drawable/ vectors, shapes, images
├─ mipmap/ launcher icons
├─ font/ font resources
├─ menu/ menu definitions
├─ navigation/ navigation graphs
├─ raw/ raw files with generated IDs
└─ xml/ general structured XML configuration

Files in assets/ retain file-like paths and do not receive normal R IDs. Choose res/raw when a generated ID/resource stream is useful; choose assets for original hierarchy/names and AssetManager access.

Default and alternative resources​

values/strings.xml default
values-ta/strings.xml Tamil
values-night/colors.xml dark theme
drawable-hdpi/product.png high-density bitmap
layout-sw600dp/checkout.xml View layout for sufficient width

Every required resource needs a safe default unless the resource system explicitly guarantees another fallback. A string existing only in values-en can fail on an unsupported locale because no default value exists.

How selection works​

Android does not count matching qualifiers and pick the directory with the most. It:

  1. removes alternatives that contradict the device configuration;
  2. evaluates qualifier types in documented precedence order;
  3. narrows candidates using the first relevant higher-precedence qualifier;
  4. continues until the best match remains;
  5. handles density using closest-match/scaling rules.

The official resource guide emphasizes that qualifier precedence matters more than the number of exact matches.

Practical selection example​

Available:

drawable/banner.xml
drawable-en/banner.xml
drawable-night/banner.xml
drawable-en-night/banner.xml

Device: English + night mode.

Result: drawable-en-night/banner.xml is the best compatible candidate. If it were missing, precedence/fallback rules—not arbitrary filename order—determine the result.

Qualifier directory order matters​

drawable-night-hdpi/ ✅ valid qualifier order
drawable-hdpi-night/ ❌ ignored/invalid ordering

Do not invent combinations from intuition. Android Studio and official qualifier tables encode a defined order.

Version qualifiers​

values/styles.xml
values-v31/styles.xml

The v31 value is considered only where that API-level configuration is supported. Always keep a default compatible resource for lower versions.

❌ Avoid duplicating values unnecessarily​

If the default works on all versions, do not copy it into every values-vXX folder. Alternatives should represent actual differences; duplication creates drift.

Resource references and themes​

<TextView
android:text="@string/checkout_title"
android:textColor="?attr/colorOnSurface" />
  • @string/... references a concrete resource identity.
  • ?attr/... asks the current theme to resolve an attribute.

Theme attributes let a reusable component adapt to light/dark/brand themes without hardcoding colors.

❌ Hardcoded semantic color​

android:textColor="#000000"

This may disappear in dark mode or violate brand/accessibility decisions.

✅ Theme semantic attribute​

android:textColor="?attr/colorOnSurface"

Resource merge is different from runtime selection​

At build time, resources from app source sets, build variants, and libraries are merged. At runtime, Android selects among the alternatives packaged into the chosen variant.

Build merge: which resources enter this APK?
Runtime resolution: which packaged alternative matches this device now?

Resource shrinking caveat​

Release shrinking can remove resources considered unused. Indirect/dynamic name lookup such as getIdentifier() is harder for tools to analyze and makes refactoring/shrinking unsafe.

✅ Prefer direct generated references​

imageView.setImageResource(R.drawable.order_shipped)

Use keep configuration only for justified indirect access and test the minified release—not merely debug.

Interview-ready answer

Android resources give code a stable ID while the runtime selects the best packaged alternative for the current configuration. Selection eliminates incompatible candidates and applies defined qualifier precedence; it does not simply choose the directory with the most qualifiers. I always provide required defaults, order qualifiers correctly, use theme attributes for semantic styling, distinguish build-time merging from runtime resolution, and test minified release resources.

Continue​

  1. Density, dp, sp, and scalable graphics
  2. Configuration changes and state reconstruction
  3. Localization, plurals, formatting, and RTL
  4. Manifest merging and API/device compatibility
  5. Resources interview scenarios