jdemeulenaere
02/17/2026, 12:32 PMStarr
02/17/2026, 4:33 PMjdemeulenaere
02/17/2026, 5:15 PMOleg Yukhnevich
02/17/2026, 6:15 PMjava.util.ServiceLoader), right?Oleg Yukhnevich
02/17/2026, 6:16 PMjdemeulenaere
02/21/2026, 9:20 PMOleg Yukhnevich
02/24/2026, 1:34 PMServiceLoader API, you can already do this.
I mean, as I stated above: create an interface, annotate it with some annotation (like @TopLevelApi), and use KSP to generate top-level declarations.
e.g:
@TopLevelAPI interface Composables {
@Composable fun Text(text: String)
}
// KSP will generate something like:
private val composables: Composables = ServiceLoader.load(Composables::class.java).single()
@Composable fun Text(text: String): Unit = composables.Text(text)
// in some other module, you will have implementation:
object ComposablesImpl: Composables {...}
In this case, it will be super clear that the interface defines the API, and the implementation is somehow loaded via ServiceLoader.
If needed, you can also hide Composables from the public API in different ways.
This will also allow multiple Composables implementations (for tests, per flavor, or other use cases), if needed.
Also, if this is an app, you might not need ServiceLoader at all and can use any other DI (Metro/Dagger/koin/etc) to link the implementation.
Will something like this work for you? Do you see a big downside in such an approach?
I mean, changing language is always nice, but it looks like it's already possible with the current Kotlin.