CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-compose-components--components-resources

Resource management library for Compose Multiplatform applications providing type-safe access to images, strings, fonts, and drawable assets across all platforms.

Pending
Overview
Eval results
Files

string-array-resources.mddocs/

String Array Resources

String array resources provide type-safe access to collections of localized strings. This is useful for lists of options, categories, labels, or any collection of related text entries that need to be localized together.

Core Types

class StringArrayResource(id: String, val key: String, items: Set<ResourceItem>) : Resource(id, items)

A string array resource represents an ordered collection of localized strings identified by a unique key. Each array can have different variants for different locales and configurations.

Composable Functions

String Array Loading

@Composable
fun stringArrayResource(resource: StringArrayResource): List<String>

Loads a string array resource within a Composable context. The function automatically selects the appropriate array variant based on the current environment and locale.

Usage:

@Composable
fun CategorySelection() {
    val categories = stringArrayResource(Res.array.product_categories)
    
    LazyColumn {
        items(categories) { category ->
            Text(
                text = category,
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable { onCategorySelected(category) }
                    .padding(16.dp)
            )
        }
    }
}

@Composable
fun SettingsOptions() {
    val options = stringArrayResource(Res.array.notification_options)
    
    options.forEachIndexed { index, option ->
        Row(
            modifier = Modifier.clickable { selectOption(index) },
            verticalAlignment = Alignment.CenterVertically
        ) {
            RadioButton(
                selected = selectedIndex == index,
                onClick = { selectOption(index) }
            )
            Text(text = option, modifier = Modifier.padding(start = 8.dp))
        }
    }
}

Suspend Functions

Non-Composable Array Loading

suspend fun getStringArray(resource: StringArrayResource): List<String>

Loads a string array resource outside of a Composable context using the system's resource environment.

Usage:

suspend fun loadMenuOptions(): List<String> {
    return getStringArray(Res.array.menu_options)
}

class DataLoader {
    suspend fun getAvailableLanguages(): List<String> {
        return getStringArray(Res.array.supported_languages)
    }
    
    suspend fun populateDropdown() {
        val options = getStringArray(Res.array.dropdown_items)
        dropdownAdapter.updateItems(options)
    }
}

Environment-Specific Array Loading

suspend fun getStringArray(
    environment: ResourceEnvironment,
    resource: StringArrayResource
): List<String>

Loads string array resources using a specific resource environment. This is useful for loading arrays in different locales or for testing purposes.

Parameters:

  • environment - The resource environment specifying locale, theme, and density
  • resource - The string array resource to load

Usage:

suspend fun getLocalizedOptions(locale: Locale): List<String> {
    val environment = ResourceEnvironment(
        LanguageQualifier(locale.language),
        RegionQualifier(locale.country),
        ThemeQualifier.LIGHT,
        DensityQualifier.MDPI
    )
    
    return getStringArray(environment, Res.array.localized_options)
}

suspend fun preloadArraysForMultipleLocales() {
    val locales = listOf("en", "es", "fr", "de")
    val arrays = mutableMapOf<String, List<String>>()
    
    locales.forEach { lang ->
        val environment = ResourceEnvironment(
            LanguageQualifier(lang),
            RegionQualifier(""),
            ThemeQualifier.LIGHT,
            DensityQualifier.MDPI
        )
        arrays[lang] = getStringArray(environment, Res.array.country_names)
    }
    
    return arrays
}

String Array Definition

XML Resource Format

<string-array name="days_of_week">
    <item>Monday</item>
    <item>Tuesday</item>
    <item>Wednesday</item>
    <item>Thursday</item>
    <item>Friday</item>
    <item>Saturday</item>
    <item>Sunday</item>
</string-array>

<string-array name="notification_frequencies">
    <item>Never</item>
    <item>Daily</item>
    <item>Weekly</item>
    <item>Monthly</item>
</string-array>

<string-array name="file_sizes">
    <item>Small (< 1 MB)</item>
    <item>Medium (1-10 MB)</item>
    <item>Large (10-100 MB)</item>
    <item>Very Large (> 100 MB)</item>
</string-array>

Localized String Arrays

res/
├── values/arrays.xml               # Default (English)
├── values-es/arrays.xml           # Spanish
├── values-fr/arrays.xml           # French
├── values-de/arrays.xml           # German
└── values-ja/arrays.xml           # Japanese

Example Localized Arrays:

values/arrays.xml (English):

<string-array name="months">
    <item>January</item>
    <item>February</item>
    <item>March</item>
    <!-- ... -->
</string-array>

values-es/arrays.xml (Spanish):

<string-array name="months">
    <item>Enero</item>
    <item>Febrero</item>
    <item>Marzo</item>
    <!-- ... -->
</string-array>

Common Use Cases

Dropdown Menus and Spinners

@Composable
fun LanguageSelector() {
    val languages = stringArrayResource(Res.array.available_languages)
    var expanded by remember { mutableStateOf(false) }
    var selectedIndex by remember { mutableStateOf(0) }
    
    ExposedDropdownMenuBox(
        expanded = expanded,
        onExpandedChange = { expanded = it }
    ) {
        TextField(
            value = languages[selectedIndex],
            onValueChange = {},
            readOnly = true,
            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }
        )
        
        ExposedDropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false }
        ) {
            languages.forEachIndexed { index, language ->
                DropdownMenuItem(
                    text = { Text(language) },
                    onClick = {
                        selectedIndex = index
                        expanded = false
                    }
                )
            }
        }
    }
}

List Navigation

@Composable
fun NavigationMenu() {
    val menuItems = stringArrayResource(Res.array.main_menu_items)
    val menuIcons = listOf(
        Icons.Default.Home,
        Icons.Default.Search,
        Icons.Default.Profile,
        Icons.Default.Settings
    )
    
    LazyColumn {
        itemsIndexed(menuItems) { index, item ->
            ListItem(
                headlineContent = { Text(item) },
                leadingContent = {
                    Icon(
                        imageVector = menuIcons[index],
                        contentDescription = null
                    )
                },
                modifier = Modifier.clickable {
                    onMenuItemClick(index)
                }
            )
        }
    }
}

Form Options

@Composable
fun PreferencesForm() {
    val themes = stringArrayResource(Res.array.theme_options)
    val frequencies = stringArrayResource(Res.array.sync_frequencies)
    
    Column {
        Text("Theme", style = MaterialTheme.typography.h6)
        themes.forEachIndexed { index, theme ->
            Row(verticalAlignment = Alignment.CenterVertically) {
                RadioButton(
                    selected = selectedTheme == index,
                    onClick = { selectedTheme = index }
                )
                Text(theme)
            }
        }
        
        Spacer(modifier = Modifier.height(16.dp))
        
        Text("Sync Frequency", style = MaterialTheme.typography.h6)
        frequencies.forEachIndexed { index, frequency ->
            Row(verticalAlignment = Alignment.CenterVertically) {
                RadioButton(
                    selected = selectedFrequency == index,
                    onClick = { selectedFrequency = index }
                )
                Text(frequency)
            }
        }
    }
}

Performance Considerations

Array Caching

String arrays are loaded and cached automatically:

@Composable
fun OptimizedArrayUsage() {
    // Array is loaded once and cached
    val options = stringArrayResource(Res.array.large_option_list)
    
    // Reuse the cached array across recompositions
    LazyColumn {
        items(options) { option ->
            Text(option)
        }
    }
}

Memory Management

Best Practices:

  1. Avoid very large arrays - Consider pagination for large datasets
  2. Cache frequently used arrays at application level
  3. Use lazy evaluation for arrays that might not be needed immediately
class ArrayCache {
    private val cache = mutableMapOf<StringArrayResource, List<String>>()
    
    suspend fun getCachedArray(resource: StringArrayResource): List<String> {
        return cache.getOrPut(resource) {
            getStringArray(resource)
        }
    }
}

Error Handling

Common Exceptions:

  • IllegalStateException - String array with given ID is not found
  • MissingResourceException - Resource file cannot be read

Example Error Handling:

@Composable
fun SafeArrayLoading() {
    val options = try {
        stringArrayResource(Res.array.menu_options)
    } catch (e: IllegalStateException) {
        // Provide fallback options
        listOf("Option 1", "Option 2", "Option 3")
    }
    
    options.forEach { option ->
        Text(text = option)
    }
}

Best Practices

  1. Use descriptive resource names:

    Res.array.notification_types    // Good
    Res.array.array1               // Bad
  2. Keep arrays reasonably sized:

    <!-- Good: Small, manageable array -->
    <string-array name="priority_levels">
        <item>Low</item>
        <item>Medium</item>
        <item>High</item>
        <item>Critical</item>
    </string-array>
    
    <!-- Consider alternatives for very large arrays -->
  3. Maintain consistent ordering:

    <!-- Consistent ordering across locales -->
    <string-array name="difficulty_levels">
        <item>Beginner</item>      <!-- Always first -->
        <item>Intermediate</item>  <!-- Always second -->
        <item>Advanced</item>      <!-- Always third -->
    </string-array>
  4. Group related arrays logically:

    <!-- Group by feature or screen -->
    <string-array name="profile_sections">
        <item>Personal Info</item>
        <item>Privacy Settings</item>
        <item>Notifications</item>
    </string-array>
    
    <string-array name="profile_privacy_options">
        <item>Public</item>
        <item>Friends Only</item>
        <item>Private</item>
    </string-array>
  5. Consider enum alternatives for app logic:

    // For app logic, consider using enums with localized display names
    enum class Priority {
        LOW, MEDIUM, HIGH, CRITICAL;
        
        @Composable
        fun displayName(): String = when (this) {
            LOW -> stringResource(Res.string.priority_low)
            MEDIUM -> stringResource(Res.string.priority_medium)
            HIGH -> stringResource(Res.string.priority_high)
            CRITICAL -> stringResource(Res.string.priority_critical)
        }
    }
  6. Validate array consistency across locales:

    • Ensure all localized arrays have the same number of items
    • Maintain consistent ordering across translations
    • Test with different locales to verify proper loading

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-compose-components--components-resources

docs

font-resources.md

image-drawable-resources.md

index.md

plural-string-resources.md

resource-environment.md

string-array-resources.md

string-resources.md

tile.json