$30 off During Our Annual Pro Sale. View Details »

Navigating Dependency Injection with Metro

Navigating Dependency Injection with Metro

GDG Devfest Incheon 2025에서 진행한 Metro로 KMP에서 의존성 주입 사용하기의 Speaker Deck입니다.
Thanks for Zac Sweers :)

Avatar for HyunWoo Lee

HyunWoo Lee

December 05, 2025
Tweet

More Decks by HyunWoo Lee

Other Decks in Programming

Transcript

  1. https://speakerdeck.com/l2hyuwnoo/navigating- dependency-injection-with-metro Viva Republica Android/React Native Engineer Community & Open

    Source Lover - GDG Korea Android, Kotlin User Groups Seoul - Contributer & Maintainer Making a new frontier of React Native X Android Granite ❤ Apps In Toss ❤
  2. ੄ઓࢿ ઱ੑ੉ۆ? class WeatherApp { fun run(location: String) { val

    service = WeatherService() val formatter = WeatherFormatter() } }
  3. ੄ઓࢿ ઱ੑ੉ۆ? class WeatherApp { fun run(location: String) { val

    service = WeatherService() val formatter = WeatherFormatter() val forecast = service.getForecast(location) println(formatter.format(forecast)) } }
  4. ੄ઓࢿ ઱ੑ੉ۆ? class WeatherApp { fun run(location: String) { val

    service = WeatherService() val formatter = WeatherFormatter() / / . . . } }
  5. ੄ઓࢿ ઱ੑ੉ۆ? class WeatherApp { private val service = WeatherService()

    private val formatter = WeatherFormatter() fun run(location: String) { / / . . . } }
  6. ੄ઓࢿ ઱ੑ੉ۆ? class WeatherApp { private val service =aWeatherService() private

    val formatter = WeatherFormatter() fun run(location: String) { / / . . . } } ࢲ਎ 🌸 24° ب௡ 🇯🇵 25° ׏਄ 🗽 31°
  7. Singletons class WeatherApp { private var service = WeatherService.getInstance() inner

    class Backdoor { fun setService(service: WeatherService) = // ... } }
  8. Service Locator class WeatherApp { private val service: WeatherService by

    inject() } @Test fun exampleTest() { startKoin { modules( module { single { WeatherService() } }) } / / … }
  9. ࣻز ઱ੑ class WeatherApp( private val service: WeatherService ) @Test

    fun exampleTest() { val app = WeatherApp(WeatherService()) / / . . . }
  10. ࣻز ઱ੑ class WeatherApp( private val service: WeatherService ) @Test

    fun exampleTest() { val app = WeatherApp(FakeWeatherService()) / / . . . }
  11. ࣻز ઱ੑ class WeatherApp( private val service: WeatherService private val

    formatter: WeatherFormatter ) { / / . . . } fun main() { val service = WeatherService() val formatter = WeatherFormatter() val app = WeatherApp(service, formatter) }
  12. ࣻز ઱ੑ class WeatherApp( private val service: WeatherService private val

    formatter: WeatherFormatter ) { / / . . . } fun main() { val httpClient = HttpClient() val service = WeatherService(httpClient) val formatter = WeatherFormatter() val app = WeatherApp(service, app) }
  13. ࣻز ઱ੑ class WeatherApp( private val service: WeatherService private val

    formatter: WeatherFormatter ) { / / . . . } fun main() { val cache = Cache() val httpClient = HttpClient(cache) val service = WeatherService(httpClient) val formatter = WeatherFormatter() val app = WeatherApp(service, app) }
  14. class Cache(…) class HttpClient(private val cache: Cache) class WeatherService(private val

    httpClient: HttpClient) class WeatherFormatter(…) class WeatherApp( private val service: WeatherService private val formatter: WeatherFormatter ) fun main() { val cache = Cache() val httpClient = HttpClient(cache) val service = WeatherService(httpClient) val formatter = WeatherFormatter() val app = WeatherApp(service, app) } ࣻز ઱ੑ
  15. ৵ Metroܳ ࣑݅٘աਃ? Dagger-style code gen Kotlin- fi rst Anvil

    aggrega ti on Mul ti pla tf orm Compiler plugin IDE diagnos ti cs* Metro
  16. ৵ Metroܳ ࣑݅٘աਃ? Dagger-style code gen Kotlin- fi rst Anvil

    aggrega ti on Mul ti pla tf orm Compiler plugin IDE diagnos ti cs* Metro moshix, RCP Circuit, RCP anvil-ksp compose-lints anvil
  17. Metro DI class Cache(…) class HttpClient(private val cache: Cache) class

    WeatherService(private val httpClient: HttpClient) class WeatherFormatter(…) class WeatherApp( private val service: WeatherService private val formatter: WeatherFormatter )
  18. Metro DI @Inject class Cache(…) @Inject class HttpClient(private val cache:

    Cache) @Inject class WeatherService(private val httpClient: HttpClient) @Inject class WeatherFormatter(…) @Inject class WeatherApp( private val service: WeatherService private val formatter: WeatherFormatter )
  19. Metro DI fun main() { val cache = Cache() val

    httpClient = HttpClient() val service = WeatherService(httpClient) val formatter = WeatherFormatter() val app = WeatherApp(service, formatter) }
  20. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp }

    fun main() { val app = createGraph<AppGraph>().app }
  21. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp }

    class HttpClient class WeatherFormatter class Cache class WeatherService
  22. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp }

    @Component interface AppGraph { val app: WeatherApp }
  23. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp }

    fun main() { val app = createGraph<AppGraph>().app }
  24. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp }

    fun main() { val app = createGraph<AppGraph>().app }
  25. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp }

    fun main() { val app = AppGraph.$$MetroGraph().app }
  26. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp }

    fun main() { val app = createGraph<AppGraph>().app }
  27. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp @DependencyGraph.Factory

    interface Factory { fun create(@Provides useMetric: Boolean) : AppGraph } } fun main() { val app = createGraph<AppGraph>().app }
  28. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp @DependencyGraph.Factory

    interface Factory { fun create(@Provides useMetric: Boolean) : AppGraph } } fun main() { val app = createGraph<AppGraph>().app }
  29. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp @DependencyGraph.Factory

    interface Factory { fun create(@Provides useMetric: Boolean) : AppGraph } } fun main() { val app = createGraphFactory<AppGraph.Factory>() .create(useMetric = true) .app }
  30. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp @Provides

    fun provideCache(fs: FileSystem) : Cache = Cache(fs) }
  31. Metro DI @DependencyGraph interface AppGraph : CacheProviders { val app:

    WeatherApp } interface CacheProviders { @Provides fun provideCache(fs: FileSystem) : Cache = Cache(fs) }
  32. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp @Provides

    fun provideCache() : Cache = Cache() @Provides fun provideFormatterCache() : Cache = Cache() }
  33. Metro DI @DependencyGraph interface AppGraph { val app: WeatherApp @Provides

    fun provideCache() : Cache = Cache() @Named("FormatterCache") @Provides fun provideFormatterCache() : Cache = Cache() }
  34. Injection class HttpClient( private val cache: Cache, private val timeout:

    Duration, ) { @Inject constructor(cache: Cache) : this(cache, 30.seconds) }
  35. Metro DI @Inject class Cache @Inject class HttpClient( private val

    cache: Cache ) @Inject class WeatherService( private val httpClient: HttpClient ) @Inject class WeatherFormatter @Inject class WeatherApp( private val service: WeatherService private val formatter: WeatherFormatter ) @DependencyGraph interface AppGraph { val app: WeatherApp } fun main() { val app = createGraph<AppGraph>().app }
  36. Scoping @SingleIn(AppScope : : class) @Inject class WeatherService( private val

    httpClient: HttpClient ) @Inject class WeatherApp( private val service: WeatherService private val formatter: WeatherFormatter ) @DependencyGraph interface AppGraph { val app: WeatherApp } Always same instance
  37. Scoping ӝࠄ੸ਵ۽ ݽٚ bindingҗ Ӓې೐ח scope ૑੿੉ উغয੓਺ Scope੉ ૑੿ػ

    ߄ੋ٬ٜী ೠ೧ࢲ double-checked lockingਵ۽ ૑ো ୡӝച Scope਷ bindingਸ ੿੄ೞח ଃীࢲ ࢶ঱, ੉ܳ ࢎਊೞח ଃীࢲ scopeਸ ঌ ೙ਃח হ਺ ౠ੿ binding type਷ scope ૑੿ ࠛо
  38. @Binds Binding impl types as interfaces they implement Binding types

    into multibindings @Binds val Int.bind: Number @Binds @IntoSet val Int.bind: Number
  39. @Binds Binding impl types as interfaces they implement Binding types

    into multibindings Binding types as nullable variants @Binds val Int.bind: Number @Binds @IntoSet val Int.bind: Number @Binds val Int.bind: Int?
  40. @Binds Binding impl types as interfaces they implement Binding types

    into multibindings Binding types as nullable variants Binding types with different quali fi ers @Binds val Int.bind: Number @Binds @IntoSet val Int.bind: Number @Binds val Int.bind: Int? @Binds @Named("timeout") val Int.bind: Int
  41. Assisted Injection @Inject class UserRepository( @Assisted val id: String, val

    httpClient: HttpClient, val db: UserDb ) { @AssistedFactory interface Factory { fun create(id: String) : UserRepository } }
  42. Assisted Injection @Inject class UserRepository( @Assisted val id: String, val

    httpClient: HttpClient, val db: UserDb ) { @AssistedFactory interface Factory { fun create(id: String) : UserRepository } }
  43. Assisted Injection @Inject class WeatherApp( val factory: UserRepository.Factory ) {

    fun run() { val userRepo = factory.create("d3938c4891ae") } } @Inject class UserRepository( @Assisted val id: String, val httpClient: HttpClient, val db: UserDb ) { @AssistedFactory interface Factory { fun create(id: String) : UserRepository } }
  44. Multibindings @DependencyGraph interface AppGraph { val interceptors: Set<Interceptor> val eventHandlers:

    Map<String, EventHandler> @Provide @IntoSet fun provideLoggingInterceptor() : Interceptor = LoggingInterceptor() }
  45. Multibindings @DependencyGraph interface AppGraph { val interceptors: Set<Interceptor> val eventHandlers:

    Map<String, EventHandler> @Provide @IntoSet fun provideLoggingInterceptor() : Interceptor = LoggingInterceptor() } @Inject @IntoMap @StringKey("ping") class PingHandler : EventHandler
  46. Multibindings @DependencyGraph interface AppGraph { @Multibinds(allowEmpty = true) val interceptors:

    Set<Interceptor> @Multibinds(allowEmpty = true) val eventHandlers: Map<String, EventHandler> }
  47. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache } @Inject class CacheImpl(…) : Cache
  48. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache } @Inject class CacheImpl(…) : Cache
  49. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache @Binds val CacheImpl.bind: Cache } @Inject class CacheImpl(…) : Cache
  50. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache } @ContributesBinding(AppScope : : class) @Inject class CacheImpl(…) : Cache
  51. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph :

    CacheImpl.AppScope$$Contribution { val cache: Cache } @ContributesBinding(AppScope : : class) @Inject class CacheImpl(…) : Cache { @MetroContribution interface AppScope$$Contribution { @Binds val CacheImpl.bind: Cache } }
  52. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache } @ContributesBinding(AppScope : : class) @Inject class CacheImpl(…) : Cache
  53. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache } @ContributesBinding(AppScope : : class) @Inject class CacheImpl(…) : Cache, Closeable
  54. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache } @ContributesBinding(AppScope : : class, binding = binding<Cache>()) @Inject class CacheImpl(…) : Cache, Closeable
  55. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache<Forecast> } @ContributesBinding(AppScope : : class, binding = binding<Cache<Forecast > > ()) @Inject class CacheImpl(…) : Cache<Forecast>, Closeable
  56. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val cache: Cache } @ContributesBinding(AppScope : : class) @Inject class CacheImpl(…) : Cache
  57. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val interceptors: Set<Interceptor> } @ContributesIntoSet(AppScope : : class) @Inject class LogcatInterceptor(…) : Interceptor
  58. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph {

    val eventHandlers: Map<String, EventHandler> } @Inject @ContributesIntoMap(AppScope : : class) @StringKey("ping") class PingHandler : EventHandler
  59. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph @ContributesTo(AppScope

    : : class) interface Accessors { val eventHandlers: Map<String, EventHandler> }
  60. What's a Contribution? @DependencyGraph(AppScope : : class) interface AppGraph :

    Accessors @ContributesTo(AppScope : : class) interface Accessors { val eventHandlers: Map<String, EventHandler> }
  61. @DependencyGraph(AppScope : : class) interface AppGraph { val cache: Cache

    val interceptors: Set<Interceptor> val eventHandlers: Map<String, EventHandler> } @ContributesIntoSet(AppScope : : class) @Inject class LogcatInterceptor(…) : Interceptor @Inject @ContributesIntoMap(AppScope : : class) @StringKey("ping") class PingHandler : EventHandler @ContributesBinding(AppScope : : class) @Inject class CacheImpl(…) : Cache :lib - network :app :lib - events :lib - cache
  62. Graph Extensions @GraphExtension interface LoggedInGraph { val user: User }

    @DependencyGraph interface AppGraph { val loggedInGraph: LoggedInGraph }
  63. Graph Extensions Factories that you can declare instead @GraphExtension interface

    LoggedInGraph { val user: User } @DependencyGraph interface AppGraph { val loggedInGraph: LoggedInGraph }
  64. Graph Extensions Factories that you can declare instead @GraphExtension interface

    LoggedInGraph { val user: User @GraphExtension.Factory interface Factory { fun create(@Provides id: String) : LoggedInGraph } } @DependencyGraph interface AppGraph { val loggedInGraphFactory: LoggedInGraph.Factory }
  65. Graph Extensions Factories that you can declare instead @GraphExtension interface

    LoggedInGraph { val user: User @GraphExtension.Factory interface Factory { fun createLoggedInGraph() : LoggedInGraph } } @DependencyGraph interface AppGraph : LoggedInGraph.Factory / / usage val loggedInGraph = appGraph.createLoggedInGraph()
  66. Graph Extensions Factories that you can declare instead Scope annotations

    @GraphExtension @SingleIn(LoggedInScope : : class) interface LoggedInGraph { val user: User }
  67. Graph Extensions Factories that you can declare instead Scope annotations

    Aggregation scopes @GraphExtension(LoggedInScope : : class) interface LoggedInGraph { val user: User }
  68. Graph Extensions Factories that you can declare instead Scope annotations

    Aggregation scopes Provider/Binds callables @GraphExtension(LoggedInScope : : class) interface LoggedInGraph { val user: User @Provides fun provideUser() : User = … }
  69. Graph Extensions Factories that you can declare instead Scope annotations

    Aggregation scopes Provider/Binds callables Their own extensions! @GraphExtension interface LoggedInActivityGraph { val user: User val activity: Activity } @GraphExtension interface LoggedInGraph { val user: User val loggedInActivityGraph: LoggedInActivityGraph } @DependencyGraph interface AppGraph { val loggedInGraph: LoggedInGraph }
  70. о੢ рױೠ Gradle ౵੉೐ۄੋ @DependencyGraph interface AppGraph { val app:

    WeatherApp } kotlinc (Frontend and Backend) compileKotlin .class f i les
  71. ݣ౭೒ۖಬীࢲח? @DependencyGraph interface AppGraph { val app: WeatherApp } kotlinc

    (Frontend and Backend) compileKotlin .class .js .wasm . . .
  72. KSP ࠽٘ ౵੉೐ۄੋ @DependencyGraph interface AppGraph { val app: WeatherApp

    } <compiled binaries> kotlinc (Frontend only) KSP source f i les kotlinc (Frontend and Backend) compileKotlin
  73. kotlinc (Frontend only) Stub gen .java f i les Kapt

    (javac) Kapt source f i les kotlinc (Frontend and Backend) compileKotlin .class f i les KAPTܳ ࢎਊೠ׮ݶ?
  74. kotlinc (Frontend only) Stub gen .java f i les Kapt

    (javac) Kapt source f i les kotlinc (Frontend and Backend) compileKotlin .class f i les javac compileJava More .class f i les KAPTܳ ࢎਊೠ׮ݶ?
  75. kotlinc (Frontend only) Stub gen .java f i les Kapt

    (javac) Kapt source f i les kotlinc (Frontend and Backend) compileKotlin .class f i les javac compileJava More .class f i les HILT ࠽٘ ౵੉೐ۄੋ javac :hiltJavaCompileDebug Even more .class f i les
  76. kotlinc (Frontend only) Stub gen .java f i les Kapt

    (javac) Kapt source f i les kotlinc (Frontend and Backend) compileKotlin .class f i les javac compileJava More .class f i les HILT ࠽٘ ౵੉೐ۄੋ javac :hiltJavaCompileDebug Even more .class f i les
  77. Metro Build Pipeline @DependencyGraph interface AppGraph { val app: WeatherApp

    } kotlinc (Frontend and Backend) compileKotlin binary f i les
  78. Metro Build Pipeline @DependencyGraph interface AppGraph { val app: WeatherApp

    } kotlinc (Frontend and Backend) compileKotlin binary f i les
  79. Metro Build Pipeline binary f i les Frontend Backend FIR

    IR Lowering Parse/PSI Source f i les
  80. Metro Build Pipeline binary f i les Frontend Backend FIR

    IR Lowering Parse/PSI f i r2ir Source f i les
  81. Declaration ࢤࢿ Constructor-injected classes/providers @Inject class Cache { / /

    Generated by Metro class $$MetroFactory : Factory<Cache> { constructor() companion object { fun create() : $$MetroFactory fun newInstance() : Cache } } }
  82. Declaration ࢤࢿ Constructor-injected classes/providers Assisted factory impls @AssistedFactory interface Factory

    { fun create(id: String) : UserRepository / / Generated by Metro class $$Impl : Factory }
  83. Declaration ࢤࢿ Constructor-injected classes/providers Assisted factory impls Contribution interfaces @ContributesBinding(AppScope

    : : class) @Inject class CacheImpl(…) : Cache { / / Generated by Metro @MetroContribution interface AppScope$$Contribution }
  84. Declaration ࢤࢿ @DependencyGraph.Factory interface Factory { fun create() : AppGraph

    / / Generated in FIR class $$Impl : Factory { constructor() } }
  85. Declaration ࢤࢿ @DependencyGraph.Factory interface Factory { fun create() : AppGraph

    / / Generated in FIR class $$Impl : Factory { constructor() } } @DependencyGraph.Factory interface Factory { fun create() : AppGraph class $$Impl : Factory { constructor() { } / / Implemented in IR override fun create() : AppGraph = AppGraph.$$MetroGraph() } }
  86. Super t ype ࢤࢿ @DependencyGraph(AppScope : : class) interface AppGraph

    @ContributesBinding(AppScope : : class) @Inject class CacheImpl(…) : Cache { / / Generated by Metro @MetroContribution interface AppScope$$Contribution } @ContributesTo(AppScope : : class) interface NetworkProviders { / / . . . }
  87. Checkers ױ ೞա੄ ୶࢚ ೣࣻ݅ оઉঠ ೞח૑ ೣࣻо dependency graphܳ

    ߈ജೞח૑ ਬബೠ ഋక੄ ಁ۞޷ఠܳ о૑Ҋ ੓ח૑ …੉৻ীب 100ѐ ؊ object DependencyGraphCreatorChecker
  88. Metro Build Pipeline binary f i les Frontend Backend FIR

    IR Lowering Parse/PSI f i r2ir Source f i les
  89. IR ߸ജ 1. FIRױীࢲ ࢤࢿೠ Binds ೣٜࣻਸ पઁ۽ ҳഅೞӝ 2.

    Ӓ ৻ী աݠ૑ ݽٚ Ѫٜী ؀ೠ ߸ജ ੘স
  90. Metro IR Pipeline 1. Ӓې೐о ইצ ௿ېझٜਸ ݢ੷ ߸ജ 2.

    ੄ઓࢿ Ӓې೐ܳ ߸ജ A. Ӓې೐ ҳࢿ ؘ੉ఠ(߄ੋ٬, ܖ౟, GraphExtension) ࣻ૘ B. GraphExtension ୊ܻ C. BindingGraph ࢤࢿ D. ਬബࢿ Ѩࢎ E. IR Ӓې೐ ҳഅ • ߄ੋ٬ٜ ଻ਕ֍ӝ • Tarjan validation(ъೠਃࣗ Ѿ೤ Ѩ ࢎ) + Kahn sorting(ਤ࢚੿۳) • Ѿҗ ߈ജ • ੿۳ػ(top sorted) • ب׳ оמೠ(reachable) • ૑ো୊ܻ೧ঠ ೡ(deferred) ఃٜ
  91. @Inject @SingleIn(AppScope : : class) class WeatherService( httpClient: HttpClient )

    @Inject class WeatherFormatter(…) @Inject class WeatherApp( service: WeatherService formatter: WeatherFormatter ) @DependencyGraph @SingleIn(AppScope : : class) interface AppGraph { val app: WeatherApp @Provides fun provideCache() : Cache = Cache() @Provides fun provideHttpClient(cache: Cache) : HttpClient = HttpClient(cache) } Metro IR Pipeline
  92. Metro IR Pipeline @DependencyGraph @SingleIn(AppScope : : class) interface AppGraph

    { val app: WeatherApp @Provides fun provideCache() : Cache = Cache() @Provides fun provideHttpClient(cache: Cache) : HttpClient = HttpClient(cache) }
  93. Metro IR Pipeline Scope — @SingleIn(AppScope : : class) @DependencyGraph

    interface AppGraph { val app: WeatherApp @Provides fun provideCache() : Cache = Cache() @Provides fun provideHttpClient( cache: Cache ) : HttpClient = HttpClient(cache) }
  94. Metro IR Pipeline Scope — @SingleIn(AppScope : : class) IrBinding.Provided

    — Cache @DependencyGraph interface AppGraph { val app: WeatherApp @Provides fun provideHttpClient( cache: Cache ) : HttpClient = HttpClient(cache) }
  95. Metro IR Pipeline Scope — @SingleIn(AppScope : : class) IrBinding.Provided

    — Cache IrBinding.Provided — HttpClient @DependencyGraph interface AppGraph { val app: WeatherApp }
  96. Metro IR Pipeline Scope — @SingleIn(AppScope : : class) IrBinding.Provided

    — Cache IrBinding.Provided — HttpClient Accessor — app: WeatherApp @DependencyGraph interface AppGraph
  97. Metro IR Pipeline WeatherApp class HttpClient class WeatherFormatter class Cache

    class WeatherService BindingLookup Cache: IrBinding.Provided HttpClient: IrBinding.Provided
  98. Metro IR Pipeline Kahn's Topo Sor t WeatherApp (IrBinding.ConstructorInjected) WeatherFormatter

    (IrBinding.ConstructorInjected) WeatherService (IrBinding.ConstructorInjected) Cache (IrBinding.Provided) HttpClient (IrBinding.Provided)
  99. Metro IR Pipeline Kahn's Topo Sor t Cache (IrBinding.Provided) HttpClient

    (IrBinding.Provided) WeatherFormatter (IrBinding.ConstructorInjected) WeatherService (IrBinding.ConstructorInjected) WeatherApp (IrBinding.ConstructorInjected)
  100. Metro IR Pipeline @DependencyGraph @SingleIn(AppScope : : class) interface AppGraph

    { val app: WeatherApp } Cache (IrBinding.Provided) HttpClient (IrBinding.Provided) WeatherFormatter (IrBinding.ConstructorInjected) WeatherService (IrBinding.ConstructorInjected) WeatherApp (IrBinding.ConstructorInjected)
  101. Metro IR Pipeline class $$MetroGraph : AppGraph { } Cache

    (IrBinding.Provided) HttpClient (IrBinding.Provided) WeatherFormatter (IrBinding.ConstructorInjected) WeatherService (IrBinding.ConstructorInjected) WeatherApp (IrBinding.ConstructorInjected)
  102. Metro IR Pipeline class $$MetroGraph : AppGraph { } ProviderFieldCollector

    Cache (IrBinding.Provided) HttpClient (IrBinding.Provided) WeatherFormatter (IrBinding.ConstructorInjected) WeatherService (IrBinding.ConstructorInjected) WeatherApp (IrBinding.ConstructorInjected)
  103. Metro IR Pipeline Cache (IrBinding.Provided) HttpClient (IrBinding.Provided) WeatherFormatter (IrBinding.ConstructorInjected) WeatherApp

    (IrBinding.ConstructorInjected) class $$MetroGraph : AppGraph { private val weatherServiceProvider: Provider<WeatherService> }
  104. Metro IR Pipeline WeatherFormatter (IrBinding.ConstructorInjected) WeatherApp (IrBinding.ConstructorInjected) class $$MetroGraph :

    AppGraph { private val weatherServiceProvider: Provider<WeatherService> = DoubleCheck.provider(…) }
  105. Metro IR Pipeline WeatherFormatter (IrBinding.ConstructorInjected) WeatherApp (IrBinding.ConstructorInjected) class $$MetroGraph :

    AppGraph { private val weatherServiceProvider: Provider<WeatherService> = DoubleCheck.provider( WeatherService.$$MetroFactory.create( $$HttpClientProvider.create( $$CacheProvider() ) ) ) }
  106. Metro IR Pipeline class $$MetroGraph : AppGraph { private val

    weatherServiceProvider: Provider<WeatherService> = DoubleCheck.provider( WeatherService.$$MetroFactory.create( $$HttpClientProvider.create( $$CacheProvider() ) ) ) override val app: WeatherApp get() = WeatherApp$$MetroFactory.create( this.weatherServiceProvider, WeatherFormatter$$MetroFactory.create() ).invoke() }
  107. Metro IR Pipeline class $$MetroGraph : AppGraph { private val

    weatherServiceProvider: Provider<WeatherService> = DoubleCheck.provider( WeatherService.$$MetroFactory.create( $$HttpClientProvider.create( $$CacheProvider() ) ) ) override val app: WeatherApp get() = WeatherApp$$MetroFactory.create( this.weatherServiceProvider, WeatherFormatter$$MetroFactory.create() ).invoke() }
  108. ੉৻ী ׮ܲ Ѫٜ • ૐ࠙࠽٘-ౠ൤ য֢ప੉࣌ ҙ۲ ઱੄ • createGraph()

    ৬ createGraphFactory() ഐ୹ ߸ഋ val graph = createGraph<AppGraph>() val graph = AppGraph.$$MetroGraph()
  109. Advanced Usage Binding containers @Includes Member injection Valid cycles Optional

    Top-level function injection Contribution replacements/excludes Compose integration Repor t s Circuit
  110. Component Interop @Component interface StartupComponent { val httpClient: HttpClient /

    / . . . } @DependencyGraph interface AppGraph { @DependencyGraph.Factory interface Factory { fun create( @Includes startupComponent: StartupComponent ) : AppGraph } } https://zacsweers.github.io/metro/latest/adoption.html
  111. Annotations Interop @Component interface StartupComponent { val httpClient: HttpClient }

    class HttpClient @Inject constructor( val cache: Provider<Cache> ) metro { interop { enableDagger() enableAnvil() } } https://zacsweers.github.io/metro/latest/adoption.html