1

I spent far too long trying to work out how to pass a number of Migration instances to a Room database builder for a Dagger2 module.

The Room database builder requires context and the database name.

Room.databaseBuilder(context, Database::class.java, dbName)
                .build()

Migrations can be added to the builder with the addMigrations method which takes vararg migrations: Migration!

One option is to create the builder.

val builder = Room.databaseBuilder(context, Database::class.java, dbName)

And then forEach through the migrations

migrations.forEach { builder.addMigrations(it) }

however this is messy and unnecessary, and the spread operator should be used instead.

I managed to miss this as the only documentation I found for the spread operator was a single sentence in the docs.

When we call a vararg-function, we can pass arguments one-by-one, e.g. asList(1, 2, 3), or, if we already have an array and want to pass its contents to the function, we use the spread operator (prefix the array with *)

2

1 Answer 1

4

In order to pass the array to the function. The array just needs to be prefixed with an asterisk *.

val migrations: Array<Migration>
Room.databaseBuilder(context, Database::class.java, dbName)
                .addMigrations(*migrations)
                .build()

In general if we have

fun foo(vararg things: Type) {
    //Do something with the things
}

We can call foo with arrayOf, or with an Array.

foo(*Array(n, { it.toType()}))
foo(*arrayOf(instance1, instance2, instance3))
val array = Array<Type>(n, {it.toType()})
foo(*array)
Sign up to request clarification or add additional context in comments.

5 Comments

the documentation already mentioned spread operator here and here. so publish it here is unnecessary.
I saw the second link. What I was looking for, and didn't see originally, was an explanation like stackoverflow.com/documentation/kotlin/5835/… this, explaining what the spread is doing rather than just saying "stick an asterisk before your" argument. I also wanted to find out if there is a particular reason for having the operator, rather than automatically spreading any array passed to a vararg method.
Hi, there is a demo about asList at the bottom in the second link. :)
I did see it. Thinking about the reason for the operator, I suppose if I have vararg things: Any and pass an array to it, it is not clear whether the array is a single argument, or the array contents are individual arguments, which is why an explicit * operator is required. Thanks for the help.
Hi, the asList function signature is already tell you that will spreads all array elements into the parameters one-by-one. in short: arrayOf(1,*arrayOf(2),3) is equivalent to arrayOf(1,2,3).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.