In Kotlin, What's the best way to iterate through an Android Cursor object and put the results into a list?
My auto-converted Java:
val list = ArrayList<String>()
while (c.moveToNext()) {
list.add(getStringFromCursor(c))
}
Is there a more idiomatic way? In particular, can it be done in a single assignment of a read-only list? E.g....
val list = /*mystery*/.map(getStringFromCursor)
... or some other arrangement, where the list is assigned fully-formed.
You can write your own map()
which checks against isClosed()
and safely close the Cursor
after iterating all over its rows like below:
fun <T> Cursor.map(f: (Cursor) -> T): List<T> {
val items = mutableListOf<T>()
use {
while (!it.isClosed && it.moveToNext()) {
items += f(it)
}
}
return items.toList()
}
Sample usage:
val contacts = cursor.map { it.toContact() }
This is what I went with in the end, using kotlin.sequences.generateSequence
...
val list = generateSequence { if (c.moveToNext()) c else null }
.map { getStringFromCursor(it) }
.toList()
My first attempt was a little shorter:
val list = (1 .. c.count).map {
c.moveToNext()
getStringFromCursor(c)
}
Both versions rely on the cursor initially being positioned before the first record (as a new cursor is). The second would throw if that wasn't the case, while the first would return a shorter list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With