Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Helping Dagger Help You (Droidcon UK 2018)

Helping Dagger Help You (Droidcon UK 2018)

As applications grow in size, Dagger can help mitigate the pain of dependency management and eliminate the boilerplate of manual dependency injection. Despite this, there are still pain points such as slower compilation times and how to inject objects like activities and views. This talk will cover functionality provided by libraries which build on top of Dagger to reduce these pain points. We'll learn what assisted injection is, why you might use it, and look at a library which simplifies the pattern. And finally we'll attempt to solve the build speed problem so that development builds are as fast as possible without sacrificing Dagger's compile-time safety.

Video: http://uk.droidcon.com/skillscasts/11617-helping-dagger-help-you

Jake Wharton

October 26, 2018
Tweet

More Decks by Jake Wharton

Other Decks in Programming

Transcript

  1. boilerplate /ˈbɔɪləpleɪt/ noun standardized pieces of text for use as

    clauses in contracts or as part of a computer program
  2. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer ) { // which profile do we load? // what initials do we render the avatar placeholder with? }Y
  3. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer ) { // which profile do we load? // what initials do we render the avatar placeholder with? // which image url do we download? }Y
  4. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer ) { lateinit var userId: String // which profile do we load? // what initials do we render the avatar placeholder with? // which image url do we download? }Y
  5. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer ) { lateinit var userId: String // which profile do we load? // what initials do we render the avatar placeholder with? // which image url do we download? }Y var userId: String = …
  6. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer ) { lateinit var userId: String // which profile do we load? // what initials do we render the avatar placeholder with? // which image url do we download? }Y var userId: String = … presenter.userId = userId
  7. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer ) { lateinit var userId: String // which profile do we load? // what initials do we render the avatar placeholder with? // which image url do we download? }Y var userId: String = … presenter.userId = userId // Use presenter…
  8. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer ) { lateinit var userId: String // … }Y var userId: String = … presenter.userId = userId // Use presenter…
  9. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y var userId: String = … presenter.userId = userId // Use presenter…
  10. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y // Use presenter…
  11. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y // Use presenter…
  12. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, @UserId var userId: String ) { // … }Y // Use presenter…
  13. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y // Use presenter…
  14. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer: AvatarRenderer )G }Y
  15. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer: AvatarRenderer )G{ fun create(userId: String) }Z }Y
  16. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer: AvatarRenderer )G{ fun create(userId: String) = ProfilePresenter(imageLoader, profilePersistence, avatarRenderer, userId) }Z }Y
  17. class ProfilePresenter(…) { // … class Factory @Inject constructor(…)G{ fun

    create(userId: String) = ProfilePresenter(imageLoader, profilePersistence, avatarRenderer, userId) }Z }Y
  18. class ProfilePresenter(…) { // … class Factory @Inject constructor(…) {

    fun create(userId: String) = ProfilePresenter(imageLoader, profilePersistence, avatarRenderer, userId) }Z }Y var userId: String = …
  19. class ProfilePresenter(…) { // … class Factory @Inject constructor(…) {

    fun create(userId: String) = ProfilePresenter(imageLoader, profilePersistence, avatarRenderer, userId) }Z }Y var userId: String = … val presenter = presenterFactory.create(userId) // Use presenter…
  20. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer: AvatarRenderer ) { fun create(userId: String) = ProfilePresenter(imageLoader, profilePersistence, avatarRenderer, userId) }Z }Y
  21. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: ImageLoader, val profilePersistence:<ProfilePersistence, val avatarRenderer: AvatarRenderer ) { fun create(userId: String) = ProfilePresenter(imageLoader, profilePersistence, avatarRenderer, userId) }Z }Y
  22. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: Provider<ImageLoader>, val profilePersistence: Provider<ProfilePersistence>, val avatarRenderer: Provider<AvatarRenderer> ) { fun create(userId: String) = ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId) }Z }Y
  23. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: Provider<ImageLoader>, val profilePersistence: Provider<ProfilePersistence>, val avatarRenderer: Provider<AvatarRenderer> ) { fun create(userId: String) = ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId) }Z }Y
  24. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: Provider<ImageLoader>, val profilePersistence: Provider<ProfilePersistence>, val avatarRenderer: Provider<AvatarRenderer> ) { fun create(userId: String) = ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId) }Z }Y
  25. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: Provider<ImageLoader>, val profilePersistence: Provider<ProfilePersistence>, val avatarRenderer: Provider<AvatarRenderer> ) { fun create(userId: String) = ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId) }Z }Y
  26. class ProfilePresenter { private final ImageLoader imageLoader; private final ProfilePersistence

    profilePersistence; private final AvatarRenderer avatarRenderer; private final String userId; ProfilePresenter( ImageLoader imageLoader, ProfilePersistence profilePersistence, AvatarRenderer avatarRenderer, String userId) { this.imageLoader = imageLoader; this.profilePersistence = profilePersistence; this.avatarRenderer = avatarRenderer; this.userId = userId; }A // … static final class Factory { private final Provider<ImageLoader> imageLoader;
  27. // … static final class Factory { private final Provider<ImageLoader>

    imageLoader; private final Provider<ProfilePersistence> profilePersistence; private final Provider<AvatarRenderer> avatarRenderer; @Inject Factory(Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { this.imageLoader = imageLoader; this.profilePersistence = profilePersistence; this.avatarRenderer = avatarRenderer; }B public ProfilePresenter create(String userId) { return new ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId); }C }D }E
  28. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: Provider<ImageLoader>, val profilePersistence: Provider<ProfilePersistence>, val avatarRenderer: Provider<AvatarRenderer> )G{ fun create(userId: String) = ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId) }Z }Y i n t e r f a c e
  29. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … interface FactoryG{ fun create(userId: String): ProfilePresenter }Z }Y
  30. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … interface Factory { fun create(userId: String): ProfilePresenter }Z }Y install(FactoryModuleBuilder() .build(ProfilePresenter::class.java))
  31. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, var userId: String ) { // … interface Factory { fun create(userId: String): ProfilePresenter }Z }Y install(FactoryModuleBuilder() .build(ProfilePresenter::class.java))
  32. class ProfilePresenter @Inject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, @Assisted var userId: String ) { // … interface Factory { fun create(userId: String): ProfilePresenter }Z }Y install(FactoryModuleBuilder() .build(ProfilePresenter::class.java))
  33. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: Provider<ImageLoader>, val profilePersistence: Provider<ProfilePersistence>, val avatarRenderer: Provider<AvatarRenderer> ) { fun create(userId: String) = ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId) }Z }Y
  34. @AutoFactory class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val

    avatarRenderer: AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: Provider<ImageLoader>, val profilePersistence: Provider<ProfilePersistence>, val avatarRenderer: Provider<AvatarRenderer> ) { fun create(userId: String) = ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId) }Z }Y
  35. @AutoFactory class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val

    avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y @Generated final class ProfilePresenterFactory { @Inject ProfilePresenterFactory(Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { … } ProfilePresenter create(userId: String) { … } }Z
  36. @AutoFactory class ProfilePresenter( @Provided val imageLoader: ImageLoader, @Provided val profilePersistence:

    ProfilePersistence, @Provided val avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y @Generated final class ProfilePresenterFactory { @Inject ProfilePresenterFactory(Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { … } ProfilePresenter create(userId: String) { … } }Z
  37. @AutoFactory class ProfilePresenter( @Provided val imageLoader: ImageLoader, @Provided val profilePersistence:

    ProfilePersistence, @Provided val avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y @Generated final class ProfilePresenterFactory { @Inject ProfilePresenterFactory(Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { … } ProfilePresenter create(userId: String) { … } }Z
  38. @AutoFactory class ProfilePresenter( @Provided val imageLoader: ImageLoader, @Provided val profilePersistence:

    ProfilePersistence, @Provided val avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y @Generated final class ProfilePresenterFactory { @Inject ProfilePresenterFactory(Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { … } ProfilePresenter create(userId: String) { … } }Z
  39. @AutoFactory class ProfilePresenter( @Provided val imageLoader: ImageLoader, @Provided val profilePersistence:

    ProfilePersistence, @Provided val avatarRenderer: AvatarRenderer, var userId: String ) { // … }Y @Generated final class ProfilePresenterFactory { @Inject ProfilePresenterFactory(Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { … } ProfilePresenter create(userId: String) { … } }Z
  40. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … class Factory @Inject constructor( val imageLoader: Provider<ImageLoader>, val profilePersistence: Provider<ProfilePersistence>, val avatarRenderer: Provider<AvatarRenderer> )G{ fun create(userId: String) = ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId) }Z }Y i n t e r f a c e
  41. class ProfilePresenter( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence, val avatarRenderer:

    AvatarRenderer, var userId: String ) { // … interface FactoryG{ fun create(userId: String): ProfilePresenter }Z }Y
  42. class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, var userId: String ) { // … interface FactoryG{ fun create(userId: String): ProfilePresenter }Z }Y
  43. class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, @Assisted var userId: String ) { // … interface FactoryG{ fun create(userId: String): ProfilePresenter }Z }Y
  44. class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, @Assisted var userId: String ) { // … @AssistedInject.Factory interface FactoryG{ fun create(userId: String): ProfilePresenter }Z }Y
  45. @Generated class AssistedInject_ProfilePresenter implements ProfilePresenter.Factory { private final Provider<ImageLoader> imageLoader;

    private final Provider<ProfilePersistence> profilePersistence; private final Provider<AvatarRenderer> avatarRenderer; @Inject AssistedInject_ProfilePresenter( Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { this.imageLoader = imageLoader; this.profilePersistence = profilePersistence; this.avatarRenderer = avatarRenderer; } @Override public ProfilePresenter create(String userId) { return new ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId); } }
  46. @Generated class AssistedInject_ProfilePresenter implements ProfilePresenter.Factory { private final Provider<ImageLoader> imageLoader;

    private final Provider<ProfilePersistence> profilePersistence; private final Provider<AvatarRenderer> avatarRenderer; @Inject AssistedInject_ProfilePresenter( Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { this.imageLoader = imageLoader; this.profilePersistence = profilePersistence; this.avatarRenderer = avatarRenderer; } @Override public ProfilePresenter create(String userId) { return new ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId); } }
  47. @Generated class AssistedInject_ProfilePresenter implements ProfilePresenter.Factory { private final Provider<ImageLoader> imageLoader;

    private final Provider<ProfilePersistence> profilePersistence; private final Provider<AvatarRenderer> avatarRenderer; @Inject AssistedInject_ProfilePresenter( Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { this.imageLoader = imageLoader; this.profilePersistence = profilePersistence; this.avatarRenderer = avatarRenderer; } @Override public ProfilePresenter create(String userId) { return new ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId); } }
  48. @Generated class AssistedInject_ProfilePresenter implements ProfilePresenter.Factory { private final Provider<ImageLoader> imageLoader;

    private final Provider<ProfilePersistence> profilePersistence; private final Provider<AvatarRenderer> avatarRenderer; @Inject AssistedInject_ProfilePresenter( Provider<ImageLoader> imageLoader, Provider<ProfilePersistence> profilePersistence, Provider<AvatarRenderer> avatarRenderer) { this.imageLoader = imageLoader; this.profilePersistence = profilePersistence; this.avatarRenderer = avatarRenderer; } @Override public ProfilePresenter create(String userId) { return new ProfilePresenter(imageLoader.get(), profilePersistence.get(), avatarRenderer.get(), userId); } }
  49. class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, @Assisted var userId: String ) { // … @AssistedInject.Factory interface Factory { fun create(userId: String): ProfilePresenter }Z }Y
  50. class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, @Assisted var userId: String ) { // … @AssistedInject.Factory interface Factory { fun create(userId: String): ProfilePresenter }Z }Y
  51. class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val profilePersistence: ProfilePersistence,

    val avatarRenderer: AvatarRenderer, @Assisted var userId: String ) { // … @AssistedInject.Factory interface Factory { fun create(userId: String): ProfilePresenter }Z }Y class AssistedInject_ProfilePresenter implements ProfilePresenter.Factory { @Inject AssistedInject_ProfilePresenter(…) }
  52. @Module abstract class AssistedModule { @Binds abstract fun bindProfilePresenterFactory( factory:

    AssistedInject_ProfilePresenter): ProfilePresenter.Factory }S @Component(modules = [PresenterModule::class]) interface PresenterComponent { // … }T
  53. @Module abstract class AssistedModule { @Binds abstract fun bindProfilePresenterFactory( factory:

    AssistedInject_ProfilePresenter): ProfilePresenter.Factory }S @Component(modules = [PresenterModule::class, AssistedModule::class]) interface PresenterComponent { // … }T
  54. @AssistedModule @Module object PresenterModule { @JvmStatic @Provides fun thing() =

    Thing("API key") }H @Module @Generated abstract class AssistedModule_PresenterModule { @Binds abstract ProfilePresenter.Factory bindProfilePresenterFactory( AssistedInject_ProfilePresenter factory) }S
  55. @AssistedModule @Module(includes = [AssistedModule_PresenterModule::class]) object PresenterModule { @JvmStatic @Provides fun

    thing() = Thing("API key") }H @Module @Generated abstract class AssistedModule_PresenterModule { @Binds abstract ProfilePresenter.Factory bindProfilePresenterFactory( AssistedInject_ProfilePresenter factory) }S
  56. @AssistedModule @Module(includes = [AssistedModule_PresenterModule::class]) object PresenterModule { @JvmStatic @Provides fun

    thing() = Thing("API key") }H @Module @Generated abstract class AssistedModule_PresenterModule { @Binds abstract ProfilePresenter.Factory bindProfilePresenterFactory( AssistedInject_ProfilePresenter factory) // … }S
  57. class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }C }B
  58. class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }C }B
  59. class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }C }B
  60. class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }C }B @Module abstract class MainActivityModule { }A
  61. class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }C }B @Module abstract class MainActivityModule { @ContributesAndroidInjector abstract fun contributeMainActivity(): MainActivity }A
  62. class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }C }B @Module abstract class MainActivityModule { @ContributesAndroidInjector abstract fun contributeMainActivity(): MainActivity }A @Component(modules = [MainActivityModule::class]) interface AppComponent
  63. class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }C }B @Module abstract class MainActivityModule { @ContributesAndroidInjector abstract fun contributeMainActivity(): MainActivity }A @Component(modules = [MainActivityModule::class]) interface AppComponent @Module abstract class MainActivityModule_ContributeMainActivity { … }
  64. class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }C }B @Module abstract class MainActivityModule { @ContributesAndroidInjector abstract fun contributeMainActivity(): MainActivity }A @Component(modules = [MainActivityModule::class]) interface AppComponent @Module abstract class MainActivityModule_ContributeMainActivity { … }
  65. class ProfileView(context: Context, attrs: AttributeSet) : ConstraintLayout(context, attrs) { lateinit

    var imageLoader: ImageLoader lateinit var avatarRenderer: AvatarRenderer }Z
  66. class ProfileView(context: Context, attrs: AttributeSet) : ConstraintLayout(context, attrs) { lateinit

    var imageLoader: ImageLoader lateinit var avatarRenderer: AvatarRenderer fun showProfile(profile: Profile) { // Use avatarRenderer… // Use imageLoader… }Y }Z
  67. class ProfileView(context: Context, attrs: AttributeSet) : ConstraintLayout(context, attrs) { lateinit

    var imageLoader: ImageLoader lateinit var avatarRenderer: AvatarRenderer fun showProfile(profile: Profile) { // Use avatarRenderer… // Use imageLoader… }Y }Z class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val avatarRenderer: AvatarRenderer, /*…*/ ) { }I
  68. class ProfileView(context: Context, attrs: AttributeSet) : ConstraintLayout(context, attrs) { lateinit

    var imageLoader: ImageLoader lateinit var avatarRenderer: AvatarRenderer fun showProfile(profile: Profile) { // Use avatarRenderer… // Use imageLoader… }Y }Z class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val avatarRenderer: AvatarRenderer, /*…*/ ) { fun attachView(view: ProfileView) { }W }I
  69. l l class ProfileView(context: Context, attrs: AttributeSet)G : ConstraintLayout(context, attrs)

    { lateinit var imageLoader: ImageLoader lateinit var avatarRenderer: AvatarRenderer fun showProfile(profile: Profile) { // Use avatarRenderer… // Use imageLoader… }Y }Z class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val avatarRenderer: AvatarRenderer, /*…*/ ) { fun attachView(view: ProfileView) { view.imageLoader = imageLoader view.avatarRenderer = avatarRenderer }W }I
  70. r r class ProfileView( context: Context, attrs: AttributeSet, val imageLoader:

    ImageLoader, val avatarRenderer: AvatarRenderer )G: ConstraintLayout(context, attrs) { fun showProfile(profile: Profile) { // Use avatarRenderer… // Use imageLoader… }Y }Z class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val avatarRenderer: AvatarRenderer, /*…*/ ) { fun attachView(view: ProfileView) { view.imageLoader = imageLoader view.avatarRenderer = avatarRenderer }W }I
  71. class ProfileView( context: Context, attrs: AttributeSet, val imageLoader: ImageLoader, val

    avatarRenderer: AvatarRenderer )G: ConstraintLayout(context, attrs) { fun showProfile(profile: Profile) { // Use avatarRenderer… // Use imageLoader… }Y }Z class ProfilePresenter @AssistedInject constructor( val imageLoader: ImageLoader, val avatarRenderer: AvatarRenderer, /*…*/ ) { fun attachView(view: ProfileView) { }W }I
  72. class ProfileView( context: Context, attrs: AttributeSet, val imageLoader: ImageLoader, val

    avatarRenderer: AvatarRenderer )G: ConstraintLayout(context, attrs) { fun showProfile(profile: Profile) { // Use avatarRenderer… // Use imageLoader… }Y }Z class ProfilePresenter @AssistedInject constructor(/*…*/) { fun attachView(view: ProfileView) { }W }I
  73. class ProfileView( context: Context, attrs: AttributeSet, val imageLoader: ImageLoader, val

    avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { fun showProfile(profile: Profile) { // Use avatarRenderer… // Use imageLoader… }Y }Z class ProfilePresenter @AssistedInject constructor(/*…*/) { fun attachView(view: ProfileView) { }W }I
  74. class LayoutInflater { interface Factory { @Nullable View onCreateView( @NonNull

    String name, @NonNull Context context, @NonNull AttributeSet attrs); }B }A
  75. class LayoutInflater { interface Factory { @Nullable View onCreateView( @NonNull

    String name, @NonNull Context context, @NonNull AttributeSet attrs); }B }A class MyAppFactory : LayoutInflater.Factory { }P
  76. class LayoutInflater { interface Factory { @Nullable View onCreateView( @NonNull

    String name, @NonNull Context context, @NonNull AttributeSet attrs); }B }A class MyAppFactory : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { }O }P
  77. class LayoutInflater { interface Factory { @Nullable View onCreateView( @NonNull

    String name, @NonNull Context context, @NonNull AttributeSet attrs); }B }A class MyAppFactory : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return TODO() }I }O }P
  78. class LayoutInflater { interface Factory { @Nullable View onCreateView( @NonNull

    String name, @NonNull Context context, @NonNull AttributeSet attrs); }B }A class MyAppFactory : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return TODO() }I return null }O }P
  79. class ProfileView( context: Context, attrs: AttributeSet, private val imageLoader: ImageLoader,

    private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { }Z
  80. class ProfileView(G @Assisted context: Context, @Assisted attrs: AttributeSet, private val

    imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { }Z
  81. class ProfileView @AssistedInject constructor(G @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { }Z
  82. class ProfileView @AssistedInject constructor(G @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory { fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z
  83. class MyAppFactory : LayoutInflater.Factory { override fun onCreateView(name: String, context:

    Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return TODO() }I return null }O }P
  84. class MyAppFactory @Inject constructor() : LayoutInflater.Factory { override fun onCreateView(name:

    String, context: Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return TODO() }I return null }O }P
  85. class MyAppFactory @Inject constructor( private val profileViewFactory: ProfileView.Factory ) :

    LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return TODO() }I return null }O }P
  86. class MyAppFactory @Inject constructor( private val profileViewFactory: ProfileView.Factory ) :

    LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return profileViewFactory.create(context, attrs) }I return null }O }P
  87. class MyAppFactory @Inject constructor( private val profileViewFactory: ProfileView.Factory, private val

    cartViewFactory: CartView.Factory ) : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return profileViewFactory.create(context, attrs) }I if (name == CartView::class.java.name) { return cartViewFactory.create(context, attrs) }I return null }O }P
  88. class MyAppFactory @Inject constructor( private val profileViewFactory: ProfileView.Factory, private val

    cartViewFactory: CartView.Factory, private val checkoutViewFactory: CheckoutView.Factory ) : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return profileViewFactory.create(context, attrs) }I if (name == CartView::class.java.name) { return cartViewFactory.create(context, attrs) }I if (name == CheckoutView::class.java.name) { return checkoutViewFactory.create(context, attrs) }I return null }O }P
  89. class MyAppFactory @Inject constructor( private val viewFactories: Map<String, ViewFactory> )

    : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { if (name == ProfileView::class.java.name) { return profileViewFactory.create(context, attrs) }I if (name == CartView::class.java.name) { return cartViewFactory.create(context, attrs) }I if (name == CheckoutView::class.java.name) { return checkoutViewFactory.create(context, attrs) }I return null }O }P private val profileViewFactory: ProfileView.Factory, private val cartViewFactory: CartView.Factory, private val checkoutViewFactory: CheckoutView.Factory
  90. class MyAppFactory @Inject constructor( private val viewFactories: Map<String, ViewFactory> )

    : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { return viewFactories[name]?.create(context, attrs) }O }P if (name == ProfileView::class.java.name) { return profileViewFactory.create(context, attrs) }I if (name == CartView::class.java.name) { return cartViewFactory.create(context, attrs) }I if (name == CheckoutView::class.java.name) { return checkoutViewFactory.create(context, attrs) }I null
  91. class MyAppFactory @Inject constructor( private val viewFactories: Map<String, ViewFactory> )

    : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { return viewFactories[name]?.create(context, attrs) }O }P interface ViewFactory { fun create(context: Context, attrs: AttributeSet): View }
  92. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory {A fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z
  93. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory : ViewFactory {A override fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z
  94. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory : ViewFactory { override fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z @Module abstract class ViewModule { }Q
  95. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory : ViewFactory { override fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z @Module abstract class ViewModule { @Binds abstract fun profileView(factory: ProfileView.Factory): ViewFactory }Q
  96. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory : ViewFactory { override fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z @Module abstract class ViewModule { @Binds @IntoMap abstract fun profileView(factory: ProfileView.Factory): ViewFactory }Q
  97. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory : ViewFactory { override fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z @Module abstract class ViewModule { @Binds @IntoMap @StringKey("com.example.ProfileView") abstract fun profileView(factory: ProfileView.Factory): ViewFactory }Q
  98. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory : ViewFactory { override fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z @Module abstract class ViewModule { @Binds @IntoMap @StringKey("com.example.ProfileView") abstract fun profileView(factory: ProfileView.Factory): ViewFactory }Q
  99. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { @AssistedInject.Factory interface Factory : ViewFactory { override fun create(context: Context, attrs: AttributeSet): ProfileView }G }Z @Module abstract class ViewModule { @Binds @IntoMap @StringKey("com.example.ProfileView") abstract fun profileView(factory: ProfileView.Factory): ViewFactory }Q
  100. class ProfileView @AssistedInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { // … }Z
  101. class ProfileView @InflationInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { // … }Z @Assisted
  102. class ProfileView @InflationInject constructor( @Assisted context: Context, @Assisted attrs: AttributeSet,

    private val imageLoader: ImageLoader, private val avatarRenderer: AvatarRenderer ) : ConstraintLayout(context, attrs) { // … }Z
  103. @Generated class InflationInject_ProfileView implements ViewFactory { private final Provider<ImageLoader> imageLoader;

    private final Provider<AvatarRenderer> avatarRenderer; @Inject InflationInject_ProfileView( Provider<ImageLoader> imageLoader, Provider<AvatarRenderer> avatarRenderer) { this.imageLoader = imageLoader; this.avatarRenderer = avatarRenderer; } @Override public View create(Context context, AttributeSet attrs) { return new ProfileView( context, attrs, imageLoader.get(), avatarRenderer.get()); } }
  104. @Generated class InflationInject_ProfileView implements ViewFactory { private final Provider<ImageLoader> imageLoader;

    private final Provider<AvatarRenderer> avatarRenderer; @Inject InflationInject_ProfileView( Provider<ImageLoader> imageLoader, Provider<AvatarRenderer> avatarRenderer) { this.imageLoader = imageLoader; this.avatarRenderer = avatarRenderer; } @Override public View create(Context context, AttributeSet attrs) { return new ProfileView( context, attrs, imageLoader.get(), avatarRenderer.get()); } }
  105. @Generated class InflationInject_ProfileView implements ViewFactory { private final Provider<ImageLoader> imageLoader;

    private final Provider<AvatarRenderer> avatarRenderer; @Inject InflationInject_ProfileView( Provider<ImageLoader> imageLoader, Provider<AvatarRenderer> avatarRenderer) { this.imageLoader = imageLoader; this.avatarRenderer = avatarRenderer; } @Override public View create(Context context, AttributeSet attrs) { return new ProfileView( context, attrs, imageLoader.get(), avatarRenderer.get()); } }
  106. @InflationModule @Module object ViewModule { }H @Module @Generated abstract class

    InflationModule_ViewModule { @Binds @IntoMap @StringKey("com.example.ProfileView") abstract ViewFactory bindProfileView( InflationInject_ProfileView factory) }S
  107. @InflationModule @Module(includes = [InflationModule_ViewModule::class]) object ViewModule { }H @Module @Generated

    abstract class InflationModule_ViewModule { @Binds @IntoMap @StringKey("com.example.ProfileView") abstract ViewFactory bindProfileView( InflationInject_ProfileView factory) }S
  108. @InflationModule @Module(includes = [InflationModule_ViewModule::class]) object ViewModule { }H @Module @Generated

    abstract class InflationModule_ViewModule { @Binds @IntoMap @StringKey("com.example.ProfileView") abstract ViewFactory bindProfileView( InflationInject_ProfileView factory) // … }S
  109. class MyAppFactory @Inject constructor( private val viewFactories: Map<String, ViewFactory> )

    : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { return viewFactories[name]?.create(context, attrs) }O }P
  110. class InflationInjectFactory @Inject constructor( private val viewFactories: Map<String, ViewFactory> )

    : LayoutInflater.Factory { override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { return viewFactories[name]?.create(context, attrs) }O }P
  111. class ProfileActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) AndroidInjection.inject(this) }B }A
  112. class ProfileActivity : Activity() { @Inject lateinit var presenterFactory: ProfilePresenter.Factory

    @Inject lateinit var inflationFactory: InflationInjectFactory override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AndroidInjection.inject(this) }B }A
  113. class ProfileActivity : Activity() { @Inject lateinit var presenterFactory: ProfilePresenter.Factory

    @Inject lateinit var inflationFactory: InflationInjectFactory override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AndroidInjection.inject(this) layoutInflater.factory = inflationFactory }B }A
  114. class ProfileActivity : Activity() { @Inject lateinit var presenterFactory: ProfilePresenter.Factory

    @Inject lateinit var inflationFactory: InflationInjectFactory override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AndroidInjection.inject(this) layoutInflater.factory = inflationFactory setContentView(R.layout.profile_view) }B }A
  115. class ProfileActivity : Activity() { @Inject lateinit var presenterFactory: ProfilePresenter.Factory

    @Inject lateinit var inflationFactory: InflationInjectFactory override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AndroidInjection.inject(this) layoutInflater.factory = inflationFactory setContentView(R.layout.profile_view) val userId = intent.getStringExtra("userId") val presenter = presenterFactory.create(userId) presenter.attachView(findViewById(R.id.profile_view) }B }A
  116. class ProfileActivity : Activity() { @Inject lateinit var presenterFactory: ProfilePresenter.Factory

    @Inject lateinit var inflationFactory: InflationInjectFactory override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AndroidInjection.inject(this) layoutInflater.factory = inflationFactory setContentView(R.layout.profile_view) val userId = intent.getStringExtra("userId") val presenter = presenterFactory.create(userId) presenter.attachView(findViewById(R.id.profile_view) }B }A l l
  117. class ProfileActivity @Inject constructor( val presenterFactory: ProfilePresenter.Factory val inflationFactory: InflationInjectFactory

    : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) AndroidInjection.inject(this) layoutInflater.factory = inflationFactory setContentView(R.layout.profile_view) val userId = intent.getStringExtra("userId") val presenter = presenterFactory.create(userId) presenter.attachView(findViewById(R.id.profile_view) }B }A @ I n j e c t l a t e i n i t r @ I n j e c t l a t e i n i t r
  118. allprojects { tasks.withType(JavaCompile).all { options.compilerArgs += [ '-Adagger.formatGeneratedSource=disabled' ]C }B

    afterEvaluate { extensions.findByName('kapt')?.arguments { arg("dagger.formatGeneratedSource", "disabled") }D }C }A
  119. allprojects { tasks.withType(JavaCompile).all { options.compilerArgs += [ '-Adagger.formatGeneratedSource=disabled' ]C }B

    afterEvaluate { extensions.findByName('kapt')?.arguments { arg("dagger.formatGeneratedSource", "disabled") }D }C }A
  120. allprojects { tasks.withType(JavaCompile).all { options.compilerArgs += [ '-Adagger.formatGeneratedSource=disabled', '-Adagger.gradle.incremental=enabled' ]C

    }B afterEvaluate { extensions.findByName('kapt')?.arguments { arg("dagger.formatGeneratedSource", "disabled") arg("dagger.gradle.incremental", "enabled") }D }C }A
  121. ButterKnife.bind(this) class ButterKnife { static Unbinder bind(Activity target) { //

    Reflection implementation… } } butterknife-reflect.aar class ButterKnife { static Unbinder bind(Activity target) { // Class.forName lookup… } } butterknife-runtime.aar
  122. dependencies { if (properties.containsKey('android.injected.invoked.from.ide')) { implementation 'com.jakewharton:butterknife-reflect:9.0.0-rc1' } else {

    implementation 'com.jakewharton:butterknife:9.0.0-rc1' kapt 'com.jakewharton:butterknife-compiler:9.0.0-rc1' }B }A
  123. dependencies { if (properties.containsKey('android.injected.invoked.from.ide')) { implementation 'com.jakewharton:butterknife-reflect:9.0.0-rc1' } else {

    implementation 'com.jakewharton:butterknife:9.0.0-rc1' kapt 'com.jakewharton:butterknife-compiler:9.0.0-rc1' // or 'annotationProcessor'… }B }A
  124. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A
  125. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = DaggerAppComponent.builder() .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  126. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = DaggerAppComponent.builder() .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  127. class DaggerReflect {C static <B> B builder(Class<B> builderClass) { return

    (B) Proxy.newProxyInstance( builderClass.getClassLoader(), new Class[] { builderClass }, ComponentBuilderInvocationHandler.create(builderClass)); }B }A
  128. class DaggerReflect {C static <B> B builder(Class<B> builderClass) { return

    (B) Proxy.newProxyInstance( builderClass.getClassLoader(), new Class[] { builderClass }, ComponentBuilderInvocationHandler.create(builderClass)); }B }A
  129. class DaggerReflect {C static <B> B builder(Class<B> builderClass) { return

    (B) Proxy.newProxyInstance( builderClass.getClassLoader(), new Class[] { builderClass }, ComponentBuilderInvocationHandler.create(builderClass)); }B }A
  130. class DaggerReflect { static <C> C create(Class<C> componentClass) { return

    (C) Proxy.newProxyInstance( componentClass.getClassLoader(), new Class[] { componentClass }, ComponentInvocationHandler.create(componentClass)); }C static <B> B builder(Class<B> builderClass) { return (B) Proxy.newProxyInstance( builderClass.getClassLoader(), new Class[] { builderClass }, ComponentBuilderInvocationHandler.create(builderClass)); }B }A
  131. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = DaggerAppComponent.builder() .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  132. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = DaggerAppComponent.builder() .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  133. final class DaggerAppComponent { static AppComponent create() { return DaggerReflect.create(AppComponent.class);

    }C static AppComponent.Builder builder() { return DaggerReflect.builder(AppComponent.Builder.class); }B }A
  134. DaggerAppComponent.builder() final class DaggerAppComponent { static AppComponent.Builder builder() { //

    real Dagger implementation… }B }A dagger-compiler.jar + dagger.jar
  135. DaggerAppComponent.builder() final class DaggerAppComponent { static AppComponent.Builder builder() { return

    DaggerReflect.builder( AppComponent.Builder.class); }B }A dagger-reflect.jar final class DaggerAppComponent { static AppComponent.Builder builder() { // real Dagger implementation… }B }A dagger-compiler.jar + dagger.jar
  136. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = DaggerAppComponent.builder() .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  137. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = DaggerReflect.builder(AppComponent.Builder::class) .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  138. class Dagger { static <B> B builder(Class<B> builderClass) { return

    DaggerReflect.builder(builderClass); }B }A
  139. class Dagger { static <B> B builder(Class<B> builderClass) { return

    DaggerReflect.builder(builderClass); }B }A class Dagger { }A
  140. class Dagger { static <B> B builder(Class<B> builderClass) { return

    DaggerReflect.builder(builderClass); }B }A class Dagger { static <B> B builder(Class<B> builderClass) { }B }A
  141. class Dagger { static <B> B builder(Class<B> builderClass) { return

    DaggerReflect.builder(builderClass); }B }A class Dagger { static <B> B builder(Class<B> builderClass) { return builderClass.getMethod("builder").invoke(null); }B }A
  142. class Dagger { static <B> B builder(Class<B> builderClass) { return

    DaggerReflect.builder(builderClass); }B }A class Dagger { static <B> B builder(Class<B> builderClass) { return builderClass.getMethod("builder").invoke(null); }B }A dagger-reflect.jar dagger-codegen.jar
  143. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = DaggerReflect.builder(AppComponent.Builder::class) .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  144. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = Dagger.builder(AppComponent.Builder::class) .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  145. @Component(modules = [AppModule::class]) interface AppComponent { fun foo(): Foo fun

    bar(): Bar fun thermosiphon(): Thermosiphon @Component.Builder interface Builder { @BindsInstance fun apiKey(@ApiKey apiKey: String) fun build(): AppComponent }B }A val component = Dagger.builder(AppComponent.Builder::class) .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build()
  146. val component = AppComponent.Builder::class.builder()G .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build() // dagger-reflect: inline fun

    <B> KClass<B>.builder(): B = DaggerReflect.builder(java) // dagger-codegen: inline fun <B> KClass<B>.builder(): B = throw UnsupportedOperationException("…")
  147. val component = AppComponent.Builder::class.builder()G .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build() // dagger-reflect: inline fun

    <B> KClass<B>.builder(): B = DaggerReflect.builder(java) // dagger-codegen: inline fun <B> KClass<B>.builder(): B = throw UnsupportedOperationException("…") // Generated from dagger-codegen-compiler: @JvmName("builderAppComponent") inline fun KClass<AppComponent.Builder>.builder() = AppComponent.builder()
  148. val component = AppComponent.Builder::class.builder()G .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build() // dagger-reflect: inline fun

    <B> KClass<B>.builder(): B = DaggerReflect.builder(java) // dagger-codegen: inline fun <B> KClass<B>.builder(): B = throw UnsupportedOperationException("…") // Generated from dagger-codegen-compiler: @JvmName("builderAppComponent") inline fun KClass<AppComponent.Builder>.builder() = AppComponent.builder()
  149. AppComponent.Builder::class.builder()G val component = .apiKey("IDt0n5RoTAc0l3CiVR3sRn13d0kdNaN1oK") .build() // dagger-reflect: inline fun

    <B> KClass<B>.builder(): B = DaggerReflect.builder(java) // dagger-codegen: inline fun <B> KClass<B>.builder(): B = throw UnsupportedOperationException("…") // Generated from dagger-codegen-compiler: @JvmName("builderAppComponent") inline fun KClass<AppComponent.Builder>.builder() = AppComponent.builder() AppComponent.builder()