If you have ever encountered development under Android on Java or Kotlin, you probably noticed how often you have to work with application resources - strings, colors, styles or dimensional values. But what to do when you need to efficiently retrieve an array of data from XMLwithout losing performance? This is where TypedArray comes to the rescue - a powerful tool that many developers underestimate.

In this article we will look at what TypedArrayis, how it differs from ordinary arrays in Android, and why its correct use can significantly speed up the loading of resources. You'll learn how to work with style attributes, extract values โ€‹โ€‹from themes, and avoid common mistakes that lead to memory leaks or application crashes. Weโ€™ll also look at practical code examples that you can immediately apply in your projects.

Regardless of whether you are a beginner or an experienced developer, understanding TypedArray will help you write cleaner and more efficient code. This is especially true for applications where performance is critical - for example, in games or multimedia players. Let's take a look at how this mechanism works under the hood.

What is TypedArray and why do you need it

TypedArray is a specialized class in Android SDKthat provides access to arrays of resources defined in XMLfiles. Unlike conventional arrays (for example String[] or int[]), it is optimized for working with application resources and allows you to retrieve them with minimal overhead.

The main advantage TypedArray is that it automatically manages the life cycle of resources and prevents memory leaksthat often arise when manually extracting data through Resources.getStringArray() or similar methods. In addition, it supports working with style attributes (for example, from styles.xml or themes.xml), which makes it indispensable for creating flexible and adaptive interfaces.

A typical usage example is retrieving an array of strings or colors from resources:

// Retrieving an array of strings from resources

TypedArray typedArray = context.obtainStyledAttributes(R.styleable.MyCustomView);

String[] items = typedArray.getTextArray(R.styleable.MyCustomView_items);

typedArray.recycle(); // Important! Freeing up resources

Without TypedArray you would have to manually parse XML or use less efficient methods, which leads to unnecessary CPU time and memory.

TypedArray vs regular arrays: key differences

At first glance, it may seem that TypedArray and standard arrays (String[], int[]) solve the same problem. However, in practice, there are fundamental differences between them that affect the performance and usability of the code.

  • ๐Ÿ”น Performance: TypedArray works directly with binary resources Android, which speeds up data access compared to manual parsing XML.
  • ๐Ÿ”น Memory management: TypedArray requires an explicit call recycle()to free up resources. Regular arrays are managed automatically by the garbage collector, but can lead to leaks if references are not cleaned up.
  • ๐Ÿ”น Styling and theme support: Only TypedArray allows you to extract values from style attributes (for example ?attr/colorPrimary), which is critical for responsive design.
  • ๐Ÿ”น Typing: TypedArray provides methods for retrieving data of specific types (getString(), getColor(), getDimension()), while regular arrays require type casting.

Consider a simple example: if you need to get an array of colors from resources, then with TypedArray it would look like this:

TypedArray colorsArray = context.resources.obtainTypedArray(R.array.my_colors);

int[] colors = new int[colorsArray.length()];

for (int i = 0; i < colorsArray.length(); i++) {

colors[i] = colorsArray.getColor(i, Color.BLACK);

}

colorsArray.recycle();

And without it, you would have to use a less flexible approach:

int[] colors = context.resources.getIntArray(R.array.my_colors);

The last method does not support working with style attributes and does not allow you to dynamically substitute values from themes.

๐Ÿ“Š How often do you use TypedArray in your projects?
Constantly
Sometimes
Redeko
Never
I donโ€™t know what it is

How to work with TypedArray: basic operations

To start using TypedArray, you need to understand several key points: how to receive it, how to extract data and how to properly release resources. Let's look at each step.

1. Getting a TypedArray

There are two main ways to get an instance TypedArray:

  • ๐Ÿ“Œ Via Resources.obtainTypedArray() โ€” for working with arrays of resources (for example, <array> v res/values/arrays.xml).
  • ๐Ÿ“Œ Via Context.obtainStyledAttributes() โ€”for extracting attributes from styles or themes.

Example for an array:

TypedArray typedArray = context.resources.obtainTypedArray(R.array.my_string_array);

Example for styles:

TypedArray attrs = context.obtainStyledAttributes(R.styleable.MyCustomView);

2. Data extraction

TypedArray provides methods for working with different types of data:

  • ๐Ÿ“ getString(int index) โ€” getting a string.
  • ๐ŸŽจ getColor(int index, int defaultColor) โ€” getting a color with a backup value.
  • ๐Ÿ“ getDimension(int index, float defaultValue) โ€” getting a size value in pixels.
  • ๐Ÿ”ข getInt(int index, int defaultValue) โ€” getting an integer.
  • ๐Ÿ–ผ๏ธ getDrawable(int index) โ€” getting a drawable resource.

However, when working with style attributes, indexes are defined in R.styleable.

3. Freeing up resources

This is the most critical moment! After use TypedArray required you need to call recycle(), otherwise a memory leak will occur. Example:

TypedArray typedArray = context.resources.obtainTypedArray(R.array.my_array);

// Working with data..

typedArray.recycle(); // Release!

โš ๏ธ Attention: If you forget to call recycle()then Android Studio may issue a warning TypedArray was not recycled when analyzing the code. In some cases, this leads to the application crashing with an error OutOfMemoryError.

โ˜‘๏ธ Checklist for working with TypedArray

Done: 0 / 4

Working with style and theme attributes

One of the most powerful uses TypedArray is working with style attributes. This allows you to create flexible interface components that adapt to the current application theme. For example, you can define a custom one that will use colors from the theme. View, which will use the colors from the theme.

Let's look at the process step by step:

1. Defining attributes in XML

First you need to declare the attributes in the file res/values/attrs.xml:

<?xml version="1.0" encoding="utf-8"?>

<resources>

<declare-styleable name="MyCustomView">

<attr name="customText" format="string"/>

<attr name="customColor" format="color"/>

<attr name="customSize" format="dimension"/>

</declare-styleable>

</resources>

2. Using attributes in layout

Now you can use these attributes in XMLmarkup:

<com.example.MyCustomView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:customText="Hello, TypedArray!"

app:customColor="@color/primary"

app:customSize="16sp"/>

3. Retrieving attributes in code

In the class MyCustomView we retrieve values โ€‹โ€‹via TypedArray:

public MyCustomView(Context context, AttributeSet attrs) {

super(context, attrs);

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);

String text = a.getString(R.styleable.MyCustomView_customText);

int color = a.getColor(R.styleable.MyCustomView_customColor, Color.BLACK);

float size = a.getDimension(R.styleable.MyCustomView_customSize, 16f);

a.recycle(); // Don't forget!

// Use the received values..

}

This approach allows your component to automatically adapt to the application theme without requiring hard coding of colors or sizes.

โš ๏ธ Attention: If you use attributes from system themes (for example, ?attr/colorPrimary), make sure they are defined in the current theme. Otherwise TypedArray will return the default value.

Optimizing performance when working with TypedArray

Although TypedArray is already optimized for working with resources, there are several tricks that will help make its use even more effective. This is especially important for applications where performance is critical - for example, in games or graphics-intensive applications.

1. Caching TypedArray

If you need to retrieve data from the same array multiple times, you should consider caching TypedArray. However, remember that you can cache only if you are sure that the resources will not change while the application is running.

private TypedArray cachedTypedArray;

public void init() {

if (cachedTypedArray == null) {

cachedTypedArray = context.resources.obtainTypedArray(R.array.my_data);

}

// We use cachedTypedArray..

}

2. Minimizing recycle() calls

If you work with several TypedArray in a row, it is better to free them immediately after use, rather than wait for the end of the method. This will reduce the memory load.

3. Using default values

Always specify fallback values โ€‹โ€‹in methods like getColor() or getDimension(). This will prevent crashes if the resource suddenly becomes unavailable:

int color = typedArray.getColor(R.styleable.MyView_customColor, Color.RED);

4. Avoid redundant calls

If you need to get multiple values โ€‹โ€‹from one TypedArray, do it in one block rather than creating a new instance for each value.

Compare the inefficient approach:

// Bad: creating a new TypedArray for each value

int color = context.obtainStyledAttributes(attrs, R.styleable.MyView)

.getColor(R.styleable.MyView_color, Color.BLACK);

float size = context.obtainStyledAttributes(attrs, R.styleable.MyView)

.getDimension(R.styleable.MyView_size, 16f);

And the optimized one:

// Good: we use one instance

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyView);

int color = a.getColor(R.styleable.MyView_color, Color.BLACK);

float size = a.getDimension(R.styleable.MyView_size, 16f);

a.recycle();

Optimization technique Advantage When to use
Caching TypedArray Reduces overhead for repeated extraction If the data is static and used frequently
Default values Prevents crashes in the absence of a resource Always, except in cases where the absence of a value is critical
Minimization recycle() Reduces memory fragmentation When working with several arrays in a row
Batch extraction Reduces the number of operations with resources When several are needed values from one array

Common mistakes and how to avoid them

Even experienced developers sometimes make mistakes when working with TypedArray. Let's look at the most common of them and learn how to prevent them.

1. Forgotten recycle() call

This is the most common error that leads to memory leaks. Always check what recycle() is called in the block finallyif there is a possibility of exceptions:

TypedArray a = null;

try {

a = context.obtainStyledAttributes(attrs, R.styleable.MyView);

// Working with data..

} finally {

if (a != null) a.recycle();

}

2. Incorrect indexes

When working with style attributes, it is easy to confuse indexes, especially if there are attrs.xml many fields. Always use generated constants from R.styleable:

// Correct:

int color = a.getColor(R.styleable.MyView_customColor, Color.BLACK);

// Incorrect (can lead to ArrayIndexOutOfBounds):

int color = a.getColor(0, Color.BLACK);

3. Ignoring default values

If you do not specify a fallback value, then if there is no resource, the method will return 0 or null, which can lead to unexpected behavior. For example, getColor() without default will return 0 (transparent color), which is not visually noticeable, but will break the logic.

4. Working with TypedArray in the background

TypedArray is not thread safe! All operations with it must be performed in the main thread (UI thread). If you need to fetch data in a background thread, do it in advance and pass the results through handlers or LiveData.

โš ๏ธ Attention: Trying to use TypedArray to AsyncTask or Coroutine to Dispatchers.IO will crash with error Only the original thread that created a view hierarchy can touch its views.
What will happen if you do not call recycle()?

Every call to obtainTypedArray() or obtainStyledAttributes() allocates a new data structure in memory. If not freed via recycle(), these objects will accumulate, which will eventually lead to a memory leak. In the worst case, the application will start to slow down or crash with an OutOfMemoryError, especially on devices with limited resources.

Practical example: dynamic theme with TypedArray

Let's look at a real example where TypedArray helps create a dynamic theme for an application. Let's say we have a setting that allows the user to choose between a light and dark theme, and we want all custom views to automatically adjust to the selected theme.

1. We define attributes in attrs.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>

<declare-styleable name="ThemedButton">

<attr name="buttonBackground" format="reference"/>

<attr name="buttonTextColor" format="color"/>

</declare-styleable>

</resources>

2. We create styles for themes

In res/values/themes.xml and res/values-night/themes.xml we define different values for attributes:


<style name="Theme.MyApp" parent="Theme.MaterialComponents.Light">

<item name="buttonBackground">@drawable/button_light</item>

<item name="buttonTextColor">@color/black</item>

</style>

<style name="Theme.MyApp" parent="Theme.MaterialComponents">

<item name="buttonBackground">@drawable/button_dark</item>

<item name="buttonTextColor">@color/white</item>

</style>

3. Implementing a custom button

In the class ThemedButton extract the attributes and apply them:

public class ThemedButton extends AppCompatButton {

public ThemedButton(Context context, AttributeSet attrs) {

super(context, attrs);

TypedArray a = context.obtainStyledAttributes(

attrs,

R.styleable.ThemedButton,

R.attr.themedButtonStyle, // Default style

0

);

Drawable background = a.getDrawable(R.styleable.ThemedButton_buttonBackground);

int textColor = a.getColor(R.styleable.ThemedButton_buttonTextColor, Color.BLACK);

setBackground(background);

setTextColor(textColor);

a.recycle();

}

}

4. We use it in markup

<com.example.ThemedButton

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Click me"

app:buttonBackground="?attr/buttonBackground"

app:buttonTextColor="?attr/buttonTextColor"/>

Now the button will automatically change its appearance depending on the selected theme, without the need to manually update its parameters.

๐Ÿ’ก

TypedArray allows you to create truly adaptive interface components that dynamically adapt to the current theme or style of the application. This eliminates the need to hard-code colors, sizes, and other attributes, making your code more flexible and maintainable.

FAQ: Answers to common questions about TypedArray

Can TypedArray be used to work with arrays defined in code (not in XML)?

No, TypedArray is intended exclusively for working with resources defined in XMLfiles (for example, in res/values/). To work with arrays created in code, use standard data structures (ArrayList, int[] etc.).

What happens if you call recycle() twice?

Call recycle() on an already freed one TypedArray will not lead to an error, but will not do anything either. However, it is better to avoid such situations, as this may indicate errors in the resource management logic.

How to access a TypedArray from a fragment?

In a fragment, you can get TypedArray through the context, for example: requireContext().obtainStyledAttributes(..). Don't forget to call recycle() in onDestroyView()if the array is used in a fragment view.

Can TypedArray be serialized?

No, TypedArray does not support serialization. If you need to store data, extract it into standard structures (for example List<String>) and serialize it already.

Why does my application crash with the error "ArrayIndexOutOfBounds" when working with TypedArray?

This error usually occurs if you are trying to access an index that does not exist. Make sure that:

  • You are using the correct constants from R.styleable.
  • In attrs.xml all attributes are correctly defined.
  • You do not exceed the length of the array (check through typedArray.length()).