0
# String Array Resources
1
2
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.
3
4
## Core Types
5
6
```kotlin { .api }
7
class StringArrayResource(id: String, val key: String, items: Set<ResourceItem>) : Resource(id, items)
8
```
9
10
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.
11
12
## Composable Functions
13
14
### String Array Loading
15
16
```kotlin { .api }
17
@Composable
18
fun stringArrayResource(resource: StringArrayResource): List<String>
19
```
20
21
Loads a string array resource within a Composable context. The function automatically selects the appropriate array variant based on the current environment and locale.
22
23
**Usage:**
24
```kotlin
25
@Composable
26
fun CategorySelection() {
27
val categories = stringArrayResource(Res.array.product_categories)
28
29
LazyColumn {
30
items(categories) { category ->
31
Text(
32
text = category,
33
modifier = Modifier
34
.fillMaxWidth()
35
.clickable { onCategorySelected(category) }
36
.padding(16.dp)
37
)
38
}
39
}
40
}
41
42
@Composable
43
fun SettingsOptions() {
44
val options = stringArrayResource(Res.array.notification_options)
45
46
options.forEachIndexed { index, option ->
47
Row(
48
modifier = Modifier.clickable { selectOption(index) },
49
verticalAlignment = Alignment.CenterVertically
50
) {
51
RadioButton(
52
selected = selectedIndex == index,
53
onClick = { selectOption(index) }
54
)
55
Text(text = option, modifier = Modifier.padding(start = 8.dp))
56
}
57
}
58
}
59
```
60
61
## Suspend Functions
62
63
### Non-Composable Array Loading
64
65
```kotlin { .api }
66
suspend fun getStringArray(resource: StringArrayResource): List<String>
67
```
68
69
Loads a string array resource outside of a Composable context using the system's resource environment.
70
71
**Usage:**
72
```kotlin
73
suspend fun loadMenuOptions(): List<String> {
74
return getStringArray(Res.array.menu_options)
75
}
76
77
class DataLoader {
78
suspend fun getAvailableLanguages(): List<String> {
79
return getStringArray(Res.array.supported_languages)
80
}
81
82
suspend fun populateDropdown() {
83
val options = getStringArray(Res.array.dropdown_items)
84
dropdownAdapter.updateItems(options)
85
}
86
}
87
```
88
89
### Environment-Specific Array Loading
90
91
```kotlin { .api }
92
suspend fun getStringArray(
93
environment: ResourceEnvironment,
94
resource: StringArrayResource
95
): List<String>
96
```
97
98
Loads string array resources using a specific resource environment. This is useful for loading arrays in different locales or for testing purposes.
99
100
**Parameters:**
101
- `environment` - The resource environment specifying locale, theme, and density
102
- `resource` - The string array resource to load
103
104
**Usage:**
105
```kotlin
106
suspend fun getLocalizedOptions(locale: Locale): List<String> {
107
val environment = ResourceEnvironment(
108
LanguageQualifier(locale.language),
109
RegionQualifier(locale.country),
110
ThemeQualifier.LIGHT,
111
DensityQualifier.MDPI
112
)
113
114
return getStringArray(environment, Res.array.localized_options)
115
}
116
117
suspend fun preloadArraysForMultipleLocales() {
118
val locales = listOf("en", "es", "fr", "de")
119
val arrays = mutableMapOf<String, List<String>>()
120
121
locales.forEach { lang ->
122
val environment = ResourceEnvironment(
123
LanguageQualifier(lang),
124
RegionQualifier(""),
125
ThemeQualifier.LIGHT,
126
DensityQualifier.MDPI
127
)
128
arrays[lang] = getStringArray(environment, Res.array.country_names)
129
}
130
131
return arrays
132
}
133
```
134
135
## String Array Definition
136
137
### XML Resource Format
138
139
```xml
140
<string-array name="days_of_week">
141
<item>Monday</item>
142
<item>Tuesday</item>
143
<item>Wednesday</item>
144
<item>Thursday</item>
145
<item>Friday</item>
146
<item>Saturday</item>
147
<item>Sunday</item>
148
</string-array>
149
150
<string-array name="notification_frequencies">
151
<item>Never</item>
152
<item>Daily</item>
153
<item>Weekly</item>
154
<item>Monthly</item>
155
</string-array>
156
157
<string-array name="file_sizes">
158
<item>Small (< 1 MB)</item>
159
<item>Medium (1-10 MB)</item>
160
<item>Large (10-100 MB)</item>
161
<item>Very Large (> 100 MB)</item>
162
</string-array>
163
```
164
165
### Localized String Arrays
166
167
```
168
res/
169
├── values/arrays.xml # Default (English)
170
├── values-es/arrays.xml # Spanish
171
├── values-fr/arrays.xml # French
172
├── values-de/arrays.xml # German
173
└── values-ja/arrays.xml # Japanese
174
```
175
176
**Example Localized Arrays:**
177
178
**values/arrays.xml (English):**
179
```xml
180
<string-array name="months">
181
<item>January</item>
182
<item>February</item>
183
<item>March</item>
184
<!-- ... -->
185
</string-array>
186
```
187
188
**values-es/arrays.xml (Spanish):**
189
```xml
190
<string-array name="months">
191
<item>Enero</item>
192
<item>Febrero</item>
193
<item>Marzo</item>
194
<!-- ... -->
195
</string-array>
196
```
197
198
## Common Use Cases
199
200
### Dropdown Menus and Spinners
201
202
```kotlin
203
@Composable
204
fun LanguageSelector() {
205
val languages = stringArrayResource(Res.array.available_languages)
206
var expanded by remember { mutableStateOf(false) }
207
var selectedIndex by remember { mutableStateOf(0) }
208
209
ExposedDropdownMenuBox(
210
expanded = expanded,
211
onExpandedChange = { expanded = it }
212
) {
213
TextField(
214
value = languages[selectedIndex],
215
onValueChange = {},
216
readOnly = true,
217
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }
218
)
219
220
ExposedDropdownMenu(
221
expanded = expanded,
222
onDismissRequest = { expanded = false }
223
) {
224
languages.forEachIndexed { index, language ->
225
DropdownMenuItem(
226
text = { Text(language) },
227
onClick = {
228
selectedIndex = index
229
expanded = false
230
}
231
)
232
}
233
}
234
}
235
}
236
```
237
238
### List Navigation
239
240
```kotlin
241
@Composable
242
fun NavigationMenu() {
243
val menuItems = stringArrayResource(Res.array.main_menu_items)
244
val menuIcons = listOf(
245
Icons.Default.Home,
246
Icons.Default.Search,
247
Icons.Default.Profile,
248
Icons.Default.Settings
249
)
250
251
LazyColumn {
252
itemsIndexed(menuItems) { index, item ->
253
ListItem(
254
headlineContent = { Text(item) },
255
leadingContent = {
256
Icon(
257
imageVector = menuIcons[index],
258
contentDescription = null
259
)
260
},
261
modifier = Modifier.clickable {
262
onMenuItemClick(index)
263
}
264
)
265
}
266
}
267
}
268
```
269
270
### Form Options
271
272
```kotlin
273
@Composable
274
fun PreferencesForm() {
275
val themes = stringArrayResource(Res.array.theme_options)
276
val frequencies = stringArrayResource(Res.array.sync_frequencies)
277
278
Column {
279
Text("Theme", style = MaterialTheme.typography.h6)
280
themes.forEachIndexed { index, theme ->
281
Row(verticalAlignment = Alignment.CenterVertically) {
282
RadioButton(
283
selected = selectedTheme == index,
284
onClick = { selectedTheme = index }
285
)
286
Text(theme)
287
}
288
}
289
290
Spacer(modifier = Modifier.height(16.dp))
291
292
Text("Sync Frequency", style = MaterialTheme.typography.h6)
293
frequencies.forEachIndexed { index, frequency ->
294
Row(verticalAlignment = Alignment.CenterVertically) {
295
RadioButton(
296
selected = selectedFrequency == index,
297
onClick = { selectedFrequency = index }
298
)
299
Text(frequency)
300
}
301
}
302
}
303
}
304
```
305
306
## Performance Considerations
307
308
### Array Caching
309
310
String arrays are loaded and cached automatically:
311
312
```kotlin
313
@Composable
314
fun OptimizedArrayUsage() {
315
// Array is loaded once and cached
316
val options = stringArrayResource(Res.array.large_option_list)
317
318
// Reuse the cached array across recompositions
319
LazyColumn {
320
items(options) { option ->
321
Text(option)
322
}
323
}
324
}
325
```
326
327
### Memory Management
328
329
**Best Practices:**
330
1. **Avoid very large arrays** - Consider pagination for large datasets
331
2. **Cache frequently used arrays** at application level
332
3. **Use lazy evaluation** for arrays that might not be needed immediately
333
334
```kotlin
335
class ArrayCache {
336
private val cache = mutableMapOf<StringArrayResource, List<String>>()
337
338
suspend fun getCachedArray(resource: StringArrayResource): List<String> {
339
return cache.getOrPut(resource) {
340
getStringArray(resource)
341
}
342
}
343
}
344
```
345
346
## Error Handling
347
348
**Common Exceptions:**
349
- `IllegalStateException` - String array with given ID is not found
350
- `MissingResourceException` - Resource file cannot be read
351
352
**Example Error Handling:**
353
```kotlin
354
@Composable
355
fun SafeArrayLoading() {
356
val options = try {
357
stringArrayResource(Res.array.menu_options)
358
} catch (e: IllegalStateException) {
359
// Provide fallback options
360
listOf("Option 1", "Option 2", "Option 3")
361
}
362
363
options.forEach { option ->
364
Text(text = option)
365
}
366
}
367
```
368
369
## Best Practices
370
371
1. **Use descriptive resource names**:
372
```kotlin
373
Res.array.notification_types // Good
374
Res.array.array1 // Bad
375
```
376
377
2. **Keep arrays reasonably sized**:
378
```xml
379
<!-- Good: Small, manageable array -->
380
<string-array name="priority_levels">
381
<item>Low</item>
382
<item>Medium</item>
383
<item>High</item>
384
<item>Critical</item>
385
</string-array>
386
387
<!-- Consider alternatives for very large arrays -->
388
```
389
390
3. **Maintain consistent ordering**:
391
```xml
392
<!-- Consistent ordering across locales -->
393
<string-array name="difficulty_levels">
394
<item>Beginner</item> <!-- Always first -->
395
<item>Intermediate</item> <!-- Always second -->
396
<item>Advanced</item> <!-- Always third -->
397
</string-array>
398
```
399
400
4. **Group related arrays logically**:
401
```xml
402
<!-- Group by feature or screen -->
403
<string-array name="profile_sections">
404
<item>Personal Info</item>
405
<item>Privacy Settings</item>
406
<item>Notifications</item>
407
</string-array>
408
409
<string-array name="profile_privacy_options">
410
<item>Public</item>
411
<item>Friends Only</item>
412
<item>Private</item>
413
</string-array>
414
```
415
416
5. **Consider enum alternatives for app logic**:
417
```kotlin
418
// For app logic, consider using enums with localized display names
419
enum class Priority {
420
LOW, MEDIUM, HIGH, CRITICAL;
421
422
@Composable
423
fun displayName(): String = when (this) {
424
LOW -> stringResource(Res.string.priority_low)
425
MEDIUM -> stringResource(Res.string.priority_medium)
426
HIGH -> stringResource(Res.string.priority_high)
427
CRITICAL -> stringResource(Res.string.priority_critical)
428
}
429
}
430
```
431
432
6. **Validate array consistency across locales**:
433
- Ensure all localized arrays have the same number of items
434
- Maintain consistent ordering across translations
435
- Test with different locales to verify proper loading