To reinforce kotlin patterns, instead of
val astronomyService = Retrofit.Builder()
.client(createHttpClient().build())
.baseUrl("https://api.nasa.gov/planetary/")
.addConverterFactory(MoshiConverterFactory.create())
.build().create<AstronomyService>()
why not the kotlin builder pattern?
val astronomyService = Retrofit.Builder().apply {
client = createHttpClient().build()
baseUrl = "https://api.nasa.gov/planetary/")
converterFactory += MoshiConverterFactory.create()
}
.build().create<AstronomyService>()
// Or, if those don't have setters
val astronomyService = Retrofit.Builder().apply {
client(createHttpClient().build())
baseUrl("https://api.nasa.gov/planetary/")
addConverterFactory(MoshiConverterFactory.create())
}
.build().create<AstronomyService>()
I like this question, because it’s exactly the kind of thing I thought about a lot when putting together the Retrofit examples for the book. I like to sweat the small stuff!
This is definitely one where you can adjust the code to suit whatever feels most natural and maintainable to you as you work through the examples. In the book, I chose to use the “old-fashioned” builder approach because it makes the code one line shorter, and because I think it looks slightly tidier without the extra brackets.
Where Kotlin’s apply()
function really shines is with classes that don’t already come with fluent builder functions or optional constructor arguments. It makes it easy to call several setter functions in a row without repeating the receiver over and over again. But since Retrofit already provides chainable builder functions to solve the same problem, I think it’s idiomatic to use them, even in Kotlin.
Thanks for asking about it! I love how Kotlin’s scope functions and default constructor arguments give us so many options for replacing Java-style fluent builders.