Skip to content

Commit

Permalink
Fix storing of Array in SavedStateHandle/Bundle (#1708)
Browse files Browse the repository at this point in the history
Fixes [CMP-5907 IllegalArgumentException: Can't put value with type
class java.util.ArrayList (Kotlin reflection is not available) into
saved state](https://youtrack.jetbrains.com/issue/CMP-5907)

## Testing
```
previousEntry.savedStateHandle[key] = arrayOf("1", "2", "3")
```
  • Loading branch information
Thomas-Vos authored Dec 12, 2024
1 parent d49b3b5 commit 2cbd13c
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ actual fun bundleOf(vararg pairs: Pair<String, Any?>): Bundle = Bundle(pairs.siz
is ShortArray -> putShortArray(key, value)

// Reference arrays
is Array<*> -> putArray(key, value)
is ArrayList<*> -> putArrayList(key, value)
// Perform extra round (with copy) because of compatibility purposes.
// Unlike Android, `listOf` result might be not castable to `ArrayList`.
Expand All @@ -225,6 +226,24 @@ actual fun bundleOf(vararg pairs: Pair<String, Any?>): Bundle = Bundle(pairs.siz
}
}

@Suppress("UNCHECKED_CAST")
private inline fun Bundle.putArray(key: String?, value: Array<*>) {
// Unlike JVM, there is no reflection available to check component type
when (value.firstOrNull()) {
is String -> putStringArray(key, value as Array<String?>?)
is CharSequence -> putCharSequenceArray(key, value as Array<CharSequence?>?)
// Narrowed alternative of Android's [putParcelableArray]
is Bundle -> putBundleArray(key, value as Array<Bundle?>?)
else -> {
if (value.isEmpty()) {
putStringArray(key, value as Array<String?>?)
} else {
throwIllegalValueType(key, value)
}
}
}
}

@Suppress("UNCHECKED_CAST")
private inline fun Bundle.putArrayList(key: String?, value: ArrayList<*>) {
// Unlike JVM, there is no reflection available to check component type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,16 @@ actual class SavedStateHandle {
is ShortArray -> true

// Reference arrays
is Array<*> -> {
// Unlike JVM, there is no reflection available to check component type
when (value.firstOrNull()) {
is String,
is CharSequence -> true
// Narrowed alternative of Android's [putParcelableArray]
is Bundle -> true
else -> value.isEmpty()
}
}
// [bundleOf] might support [List] instead of [ArrayList] in some cases.
is List<*> -> {
// Unlike JVM, there is no reflection available to check component type
Expand Down

0 comments on commit 2cbd13c

Please sign in to comment.