Search code examples
androiddependency-injectiondagger-2dagger

How to call the class method at runtime using dagger-2 in android


In my application i will be getting the various request from the single source, my job is to route the request to their particular handler. since my application uses the dagger am not able to route the request at run time.

data class MyRequestObj(type : Int, someInfo : String) 

The above class is the request object that i send to route

interface RequestHandler{
 fun performRequest(someInfo : String)
}

The above interface i will be extending in all the handler classes.

class Handler1 : RequestHandler{
  @Override
  fun performRequest(someInfo : String){

  }
}

class Handler2 : RequestHandler{
  @Override
  fun performRequest(someInfo : String){

  }
}

The above handler classes which implements RequestHandler

class Router @Inject constructor(handler1 : Handler1, handler2 :Handler2) {

     fun routeRequest(request : MyRequestObj){
        when(request.type){
         TYPE1 -> handler1.performRequest(request.someInfo)

         TYPE2 -> handler2.performRequest(request.someInfo)
    }
  }
 }

The above class routes the request, my problem is i don't want to inject all my handlers at the constructor, i need to inject them at runtime using @Named in dagger or any other way based on its type.

Can anyone help me with this.


Solution

  • Use map Multibindings to create an injectable map of your Handlers. You can use Class as keys for your handlers.

    Map<Class<?>, Provider<RequestHandler>>

    @Module
    class HandlerModule {
    
        @Provides @IntoMap
        @ClassKey(Handler1.class)
        fun provideHandler1() : RequestHandler {
            return Handler1()
        }
    
        @Provides @IntoMap
        @ClassKey(Handler1.class)
        fun provideHandler2() : RequestHandler {
            return Handler2()
        }
    
    }
    

    You can then inject the map in your Router class:

    class Router @Inject constructor(
            val handlerProviders: Map<Class<out RequestHandler>,
                    @JvmSuppressWildcards Provider<RequestHandler>>) {
    
        fun routeRequest(request: MyRequestObj) {
            val handler = when (request.type) {
                TYPE1 -> handlerProviders.get(Handler1::class.java).get()
                TYPE2 -> handlerProviders.get(Handler2::class.java).get()
                else -> null
            }
            handler?.performRequest(request.someInfo)
        }
    }