Last active
October 9, 2019 15:33
-
-
Save gfreivasc/c52e5fde20f3b4e9380658db66f7b181 to your computer and use it in GitHub Desktop.
This is an example of how to achieve MVP with injection through dagger (this version without dagger android)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.gabrielfv.sandbox6 | |
import android.app.Activity | |
import android.app.Application | |
import android.os.Bundle | |
import android.view.View | |
import android.widget.Toast | |
import dagger.* | |
import javax.inject.Inject | |
/** | |
* Main scoped component you will usually find in Android projects | |
*/ | |
@Component(modules = [AppModule::class]) | |
interface AppComponent { | |
fun mainSubcomponentFactory() : MainSubcomponent.Factory | |
} | |
class MyApplication : Application() { | |
/** | |
* Component must be visible so we can launch our subcomponent with it | |
*/ | |
lateinit var component: AppComponent | |
override fun onCreate() { | |
super.onCreate() | |
component = DaggerAppComponent.create() | |
} | |
} | |
@Subcomponent(modules = [MainModule::class]) | |
interface MainSubcomponent { | |
/** | |
* Allows us to manually inject into our activity | |
*/ | |
fun inject(activity: MainActivity) | |
@Subcomponent.Factory | |
interface Factory { | |
/** | |
* Binds the activity instance to the DI graph so we can now inject it as a dependency | |
* when within the lifetime of our subcomponent | |
*/ | |
fun create(@BindsInstance activity: MainActivity): MainSubcomponent | |
} | |
} | |
/** | |
* Module declares it's subcomponent so any component (or subcomponent) can initialize it. | |
*/ | |
@Module(subcomponents = [MainSubcomponent::class]) | |
interface AppModule | |
/** | |
* This module holds reference to MainActivity as a dependency so it cannot be included on other | |
* components. | |
*/ | |
@Module | |
interface MainModule { | |
/** | |
* Tells Dagger our MainActivity is an instance of Main.View | |
*/ | |
@Binds | |
fun bindsMainView(activity: MainActivity): Main.View | |
/** | |
* Tells Dagger our MainPresenter is an instance of Main.Presenter | |
*/ | |
@Binds | |
fun bindsMainPresenter(presenter: MainPresenter): Main.Presenter | |
} | |
interface Main { | |
interface View { | |
fun show(count: Int) | |
} | |
interface Presenter { | |
fun inc() | |
} | |
} | |
class MainActivity : Activity(), Main.View { | |
/** | |
* This dependency does not block the instantiation of our activity and prevents | |
* the cyclic dependency from breaking our code | |
*/ | |
@Inject lateinit var presenter: Main.Presenter | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
setContentView(android.R.layout.activity_list_item) | |
/** | |
* Here we get the factory of the subcomponent through our app component, | |
* create the subcomponent and then ask it to inject the dependencies needed, | |
* while our activity already exists. | |
*/ | |
(application as MyApplication).component | |
.mainSubcomponentFactory() | |
.create(this) | |
.inject(this) | |
val view = findViewById<View>(android.R.id.content) | |
view.setOnClickListener { presenter.inc() } | |
} | |
override fun show(count: Int) { | |
Toast.makeText(this, "Count $count", Toast.LENGTH_LONG).show() | |
} | |
} | |
/** | |
* The presenter is only instantiated when our activity already exists, so it can take it | |
* as a dependency. | |
*/ | |
class MainPresenter @Inject constructor(private val view: Main.View) : Main.Presenter { | |
private var count = 0 | |
override fun inc() { | |
view.show(++count) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment