Search code examples
androidkotlinmvpdaggermosby

How can i inject object into presenter in android kotlin MVP mosby app with dagger


I am trying to get dagger working in my application. After creating Module Component and MyApp i can use dagger to inject database service into view but i am having trouble doing same thing with presenter. Code:

class MyApp : Application() {

    var daoComponent: DaoComponent? = null
    private set

    override fun onCreate() {
        super.onCreate()

        daoComponent = DaggerDaoComponent.builder()
            .appModule(AppModule(this)) // This also corresponds to the name of your module: %component_name%Module
            .daoModule(DaoModule())
            .build()
    }
}

Module

@Module
class DaoModule {
    @Provides
    fun providesEstateService(): EstateService = EstateServiceImpl()
}

Component

@Singleton
@Component(modules = arrayOf(AppModule::class, DaoModule::class))
interface DaoComponent {
    fun inject(activity: MainActivity)
}

AppModule

@Module
class AppModule(internal var mApplication: Application) {

    @Provides
    @Singleton
    internal fun providesApplication(): Application {
        return mApplication
    }
}

MainActivity

class MainActivity : MvpActivity<MainView, MainPresenter>(), MainView {
    @Inject
    lateinit var estateService : EstateService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        (application as MyApp).daoComponent!!.inject(this)estateService.numberOfInvoicedEstates.toString()
    }

    override fun createPresenter(): MainPresenter = MainPresenterImpl()
}

After injecting estateService this way I can use it, but I cant figure out how do I inject service directly into the presenter. I tried doing it like this but it isn't working. Should I just pass injected objects from the activity? or maybe I should pass MyApp as an argument or make static method allowing my to get it from any place in the application?

class MainPresenterImpl 
    @Inject
    constructor(): MvpBasePresenter<MainView>(),MainPresenter {
        @Inject
        lateinit var estateService : EstateService
}

Solution

  • Your component should provide the presenter like that:

    @Component(modules = arrayOf(AppModule::class, DaoModule::class))
    @Singleton
    interface MyComponent {
       mainPresenter() : MainPresenter
    }
    

    And all dependencies the presenter needs are injected to the presenter via constructor parameters:

    class MainPresenterImpl 
        @Inject constructor(private val estateService : EstateService ) :
        MvpBasePresenter<MainView>(),MainPresenter {
       ...
    }
    

    Than in createPresenter() just grab the presenter from dagger component like this:

    class MainActivity : MvpActivity<MainView, MainPresenter>(), MainView {
    
        ...
    
        override fun createPresenter(): MainPresenter =  
           (application as MyApp).myComponent().mainPresenter()
    }
    

    Please note that the code shown above will not compile. This is just pseudocode to give you an idea how the dependency graph could look like in Dagger.