title: Dagger2 + MVP on Kotlin
body: <p>I am studying Dagger2 + MVP and doing it on Kotlin. And I have a problem in understanding either Dagger2 or MVP or there combination.</p>
  
  <p>Construction of an application and idea how it should work are very simple. The app consists of <code>MenuActivity</code> with left-side navigation and several <code>Fragments</code> (let's say 3) that should be changed in the <code>FrameLayout</code> in <code>activity_menu.xml</code>. </p>
  
  <p>I have read several articles and spend already couple of days studying Dagger2. This article I use as tutorial to build my example: <a href="https://proandroiddev.com/dagger-2-part-ii-custom-scopes-component-dependencies-subcomponents-697c1fa1cfc" rel="nofollow noreferrer">https://proandroiddev.com/dagger-2-part-ii-custom-scopes-component-dependencies-subcomponents-697c1fa1cfc</a></p>
  
  <p>In my idea, Dagger architecture should consist of three <code>@Component</code>s : (1) AppComponent, (2) MenuActivityComponent and (3) AccountFragmentComponent.
  And from my understanding and the picture of an architecture in the article my architecture can be like this: (3) depends on -> (2) depends on -> (1)</p>
  
  <p>Each <code>@Component</code> has a <code>@Module</code> : (1) AppModule, (2) MenuActivityModule and (3) AccountFragmentModule respectively. For the cleaner way of MVP dependencies, as far as I understand, both (2) MenuActivityModule and (3) AccountFragmentModule should <code>@Provide</code> <code>Presenter</code>s from MVP ideology to be <code>@Inject</code> in <code>MenuActivity</code> and other <code>Fragment</code>s, such as <code>AccountFragment</code>.</p>
  
  <p><strong>AppModule</strong></p>
  
  <pre><code>@Module
  class AppModule(val app : App){
  
      @Provides @Singleton
      fun provideApp() = app
  
  }
  </code></pre>
  
  <p><strong>AppComponent</strong></p>
  
  <pre><code>@Singleton @Component(modules = arrayOf(AppModule::class))
  interface AppComponent{
  
      fun inject(app : App)
  
      fun plus(menuActivityModule: MenuActivityModule): MenuActivityComponent
  }
  </code></pre>
  
  <p><strong>MenuActivityModule</strong></p>
  
  <pre><code>@Module
  class MenuActivityModule(val activity : MenuActivity) {
  
      @Provides
      @ActivityScope
      fun provideMenuActivityPresenter() =
          MenuActivityPresenter(activity)
  
      @Provides
      fun provideActivity() = activity
  }
  </code></pre>
  
  <p><strong>MenuActivityComponent</strong></p>
  
  <pre><code>@ActivityScope
  @Subcomponent(modules = arrayOf(MenuActivityModule::class))
  interface MenuActivityComponent {
  
      fun inject(activity: MenuActivity)
  
      fun plus(accountsModule : AccountsFragmentModule) : AccountsFragmentComponent
  }
  </code></pre>
  
  <p><strong>AccountsFragmentModule</strong></p>
  
  <pre><code>@Module
  class AccountsFragmentModule(val fragment: AccountsFragment){
  
      @FragmentScope
      @Provides
      fun provideAccountsFragmentPresenter() =
          AccountsFragmentPresenter(fragment)
  }
  </code></pre>
  
  <p><strong>AccountsFragmentComponent</strong></p>
  
  <pre><code>@FragmentScope
  @Subcomponent(modules = arrayOf(AccountsFragmentModule::class))
  interface AccountsFragmentComponent {
  
      fun inject(fragment: AccountsFragment)
  }
  </code></pre>
  
  <p>Also I have two <code>@Scope</code>s: ActivityScope and FragmentScope, so as I understand that will guarantee the existence of only one Component for the time every component is need in the application.</p>
  
  <p><strong>ActivityScope</strong></p>
  
  <pre><code>@Scope
  annotation class ActivityScope
  </code></pre>
  
  <p><strong>FragmentScope</strong></p>
  
  <pre><code>@Scope
  annotation class FragmentScope
  </code></pre>
  
  <p>In Application class I create a graph of <code>@Singleton</code> dependencies.</p>
  
  <pre><code>class App : Application(){
  
      val component : AppComponent by lazy {
          DaggerAppComponent
              .builder()
              .appModule(AppModule(this))
              .build()
      }
  
      companion object {
          lateinit var instance : App
              private set
      }
  
      override fun onCreate() {
          super.onCreate()
          component.inject(this)
      }
  
  }
  </code></pre>
  
  <p>In MenuActivity: </p>
  
  <pre><code>class MenuActivity: AppCompatActivity()
  
      @Inject lateinit var presenter : MenuActivityPresenter
  
      val Activity.app : App
      get() = application as App
  
      val component by lazy {
          app.component.plus(MenuActivityModule(this))
      }
  
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_menu)
          /* setup dependency injection */
          component.inject(this)
          /* setup UI */
          setupMenu()
          presenter.init()
      }
  
  private fun setupMenu(){
      navigationView.setNavigationItemSelectedListener({
          menuItem: MenuItem -&gt; selectDrawerItem(menuItem)
          true
      })
  
      /* Hamburger icon for left-side menu */
      supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp)
      supportActionBar?.setDisplayHomeAsUpEnabled(true)
  
      drawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.drawer_open,  R.string.drawer_close);
      drawerLayout.addDrawerListener(drawerToggle as ActionBarDrawerToggle)
      }
  private fun selectDrawerItem(menuItem: MenuItem){
  
      presenter.menuItemSelected(menuItem)
  
      // Highlight the selected item has been done by NavigationView
      menuItem.isChecked = true
      // Set action bar title
      title = menuItem.title
      // Close the navigation drawer
      drawerLayout.closeDrawers()
  }
  
  @SuppressLint("CommitTransaction")
  override fun showFragment(fragment: Fragment, isReplace: Boolean,
                            backStackTag: String?, isEnabled: Boolean)
  {
      /* Defining fragment transaction */
      with(supportFragmentManager.beginTransaction()){
  
          /* Select if to replace or add a fragment */
          if(isReplace)
              replace(R.id.frameLayoutContent, fragment, backStackTag)
          else
              add(R.id.frameLayoutContent, fragment)
  
          backStackTag?.let { this.addToBackStack(it) }
  
          commit()
      }
  
      enableDrawer(isEnabled)
  }
  
  private fun enableDrawer(isEnabled: Boolean) {
      drawerLayout.setDrawerLockMode(if(isEnabled) DrawerLayout.LOCK_MODE_UNLOCKED
                                      else DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
      drawerToggle?.onDrawerStateChanged(if(isEnabled) DrawerLayout.LOCK_MODE_UNLOCKED
                                          else DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
      drawerToggle?.isDrawerIndicatorEnabled = isEnabled
      drawerToggle?.syncState()
  }
  
  override fun onOptionsItemSelected(item: MenuItem?): Boolean {
    if (drawerToggle!!.onOptionsItemSelected(item)) {
        return true
    }
    return super.onOptionsItemSelected(item)
  }
  
  override fun onPostCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
      super.onPostCreate(savedInstanceState, persistentState)
      drawerToggle?.syncState()
  }
  
  override fun onConfigurationChanged(newConfig: Configuration?) {
      super.onConfigurationChanged(newConfig)
      drawerToggle?.onConfigurationChanged(newConfig)
  }
  }
  </code></pre>
  
  <p><strong>MainActivityPresenter</strong></p>
  
  <pre><code>class MenuActivityPresenter(val menuActivity: MenuActivity){
  
      fun init(){
          menuActivity.showFragment(AccountsFragment.newInstance(), isReplace = false)
      }
  
      fun menuItemSelected(menuItem: MenuItem){
  
          val fragment =  when(menuItem.itemId){
              R.id.nav_accounts_fragment -&gt; {
                  AccountsFragment.newInstance()
              }
              R.id.nav_income_fragment -&gt; {
                  IncomeFragment.newInstance()
              }
              R.id.nav_settings -&gt; {
                  IncomeFragment.newInstance()
              }
              R.id.nav_feedback -&gt; {
                  OutcomeFragment.newInstance()
              }
              else -&gt; {
                  IncomeFragment.newInstance()
              }
          }
  
          menuActivity.showFragment(fragment)
      }
  
  }
  </code></pre>
  
  <p><strong>activity_menu.xml</strong></p>
  
  <pre><code>&lt;android.support.v4.widget.DrawerLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:id="@+id/drawerLayout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"&gt;
  
  &lt;!-- This LinearLayout represents the contents of the screen  --&gt;
  &lt;LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical"&gt;
  
      &lt;!-- The ActionBar displayed at the top --&gt;
      &lt;include
          layout="@layout/toolbar"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" /&gt;
  
      &lt;!-- The main content view where fragments are loaded --&gt;
      &lt;FrameLayout
          android:id="@+id/frameLayoutContent"
          android:layout_width="match_parent"
          android:layout_height="match_parent" /&gt;
  
  &lt;/LinearLayout&gt;
  
  &lt;!-- The navigation drawer that comes from the left --&gt;
  &lt;!-- Note that `android:layout_gravity` needs to be set to 'start' --&gt;
  &lt;android.support.design.widget.NavigationView
      android:id="@+id/navigationView"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:layout_gravity="start"
      android:background="@android:color/white"
      app:menu="@menu/main_menu"
      app:headerLayout="@layout/nav_header"
      /&gt;
  
  &lt;/android.support.v4.widget.DrawerLayout&gt;
  </code></pre>
  
  <p>And the place where I have a breaking point in my understanding: </p>
  
  <pre><code>class AccountsFragment : Fragment() {
  
      companion object {
          fun newInstance() = AccountsFragment()
      }
  
      val Activity.app : App
         get() = application as App
  
      val component by lazy {
         app.component
             .plus(MenuActivityModule(activity as MenuActivity))
             .plus(AccountsFragmentModule(this))
      }
  
      override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
         val view = inflater?.inflate(R.layout.fragment_accounts, container, false)
         setHasOptionsMenu(true)
         component.inject(this)
         return view
     }
  
  }
  </code></pre>
  
  <p>My misunderstanding in this final part in the <code>component</code> value. I came to the situation that I need to <code>plus</code> Subcomponent of the MenuActivityComponent and give as a constructor variable MenuActivity, but I understand this is wrong and I can't create another instance even if I want that the instance should be only one in the application.</p>
  
  <p><strong>Question</strong>: Where I have a mistake? In my code, in architecture, in understanding of dependency injection or in all three? Thank you for your help!</p>