Search code examples
androidkotlindagger-2dagger

Android - Dagger injection at runtime


i need to inject the class at runtime using dagger. what my problem is am getting compile time error while injecting the class locally in method and also i was not able to inject at runtime without using constant for @Named

Example

interface PerformActionInterface{
      fun performAction()
}

class P1 : PerformActionInterface{
   override fun performAction(){
   }
}

class P2 : PerformActionInterface{
   override fun performAction(){
   }
}


class PerformAction @Inject constructor(){

      fun perform(name : String){

        @Inject
        @Named(name)
        performActionInterface : PerformActionInterface

        performActionInterface.performAction()
    }
}

were as in dagger implementation i will be doing like this

 @Binds
 @Named("p1")
 abstract bindP1Class(p1 : P1) :PerformActionInterface

 @Binds
 @Named("p2")
 abstract bindP1Class(p2 : P2) :PerformActionInterface

Any help for how to inject this at runtime ?


Solution

  • You can't annotate something in runtime, the element value in Java annotation has to be a constant expression.

    But this use case can be solved by map multibind.

    In your Module, in addition to just @Bind or @Provide, also annotate the abstract fun with @IntoMap and the map key (sorry for any error in my Kotlin)

    @Binds
    @IntoMap
    @StringKey("p1")
    abstract fun bindP1Class(p1: P1): PerformActionInterface
    
    @Binds
    @IntoMap
    @StringKey("p2")
    abstract fun bindP2Class(p2: P2): PerformActionInterface
    

    Then in your PerformAction class, declare a dependency of a map from String to PerformActionInterface, and do whatever with the map:

    // map value type can be Lazy<> or Provider<> as needed
    class PerformAction @Inject constructor(
            val map: Map<String, @JvmSuppressWildcards PerformActionInterface>) {
    
        fun perform(name: String) {
            map.get(name)?.performAction()
            // or do something if the get returns null
        }
    }