├── app
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── colors.xml
│ │ │ └── themes.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── layout
│ │ │ └── activity_main.xml
│ │ ├── values-night
│ │ │ └── themes.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ └── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ └── ca
│ │ │ └── nick
│ │ │ └── multimodulenavigation
│ │ │ ├── di
│ │ │ ├── AppComponentProvider.kt
│ │ │ ├── SubcomponentsModule.kt
│ │ │ ├── MainScope.kt
│ │ │ ├── FragmentKey.kt
│ │ │ ├── AppComponent.kt
│ │ │ ├── MainModule.kt
│ │ │ ├── MainComponent.kt
│ │ │ └── FragmentsModule.kt
│ │ │ ├── App.kt
│ │ │ ├── OnItemClickedDirections.kt
│ │ │ ├── AppFragmentFactory.kt
│ │ │ └── MainActivity.kt
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
└── build.gradle
├── detail
├── .gitignore
├── consumer-rules.pro
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── ca
│ │ │ └── nick
│ │ │ └── detail
│ │ │ └── DetailFragment.kt
│ │ └── res
│ │ └── layout
│ │ └── detail_fragment.xml
├── proguard-rules.pro
└── build.gradle
├── list
├── .gitignore
├── consumer-rules.pro
├── src
│ └── main
│ │ ├── java
│ │ └── ca
│ │ │ └── nick
│ │ │ └── list
│ │ │ ├── OnItemClicked.kt
│ │ │ ├── SomeHeavyWeightDependency.kt
│ │ │ └── ListFragment.kt
│ │ ├── AndroidManifest.xml
│ │ └── res
│ │ └── layout
│ │ └── list_fragment.xml
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── README.md
├── .gitignore
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/detail/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/list/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/list/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/detail/consumer-rules.pro:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':detail'
2 | include ':list'
3 | include ':app'
4 | rootProject.name = "multimodulenavigation"
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | multimodulenavigation
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/list/src/main/java/ca/nick/list/OnItemClicked.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.list
2 |
3 | interface OnItemClicked {
4 | fun onItemClicked()
5 | }
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nihk/multi-module-navigation/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/list/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/di/AppComponentProvider.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation.di
2 |
3 | interface AppComponentProvider {
4 | val appComponent: AppComponent
5 | }
--------------------------------------------------------------------------------
/detail/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/list/src/main/java/ca/nick/list/SomeHeavyWeightDependency.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.list
2 |
3 | import javax.inject.Inject
4 | import javax.inject.Singleton
5 |
6 | @Singleton
7 | class SomeHeavyWeightDependency @Inject constructor()
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/di/SubcomponentsModule.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation.di
2 |
3 | import dagger.Module
4 |
5 | @Module(subcomponents = [MainComponent::class])
6 | object SubcomponentsModule
--------------------------------------------------------------------------------
/detail/src/main/java/ca/nick/detail/DetailFragment.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.detail
2 |
3 | import androidx.fragment.app.Fragment
4 | import javax.inject.Inject
5 |
6 | class DetailFragment @Inject constructor() : Fragment(R.layout.detail_fragment)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # multi-module-navigation
2 | A quick and dirty project to show multi-(Gradle)module navigation facilitated by Dagger
3 |
4 | This is a repo to accompany my Medium article:
5 | https://medium.com/@nicholas.rose/multi-module-navigation-with-dagger2-f747db186343
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Dec 27 11:42:21 EST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 | .idea/
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/di/MainScope.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation.di
2 |
3 | import javax.inject.Scope
4 |
5 | @Target(
6 | AnnotationTarget.CLASS,
7 | AnnotationTarget.FUNCTION
8 | )
9 | @Retention(AnnotationRetention.RUNTIME)
10 | @Scope
11 | annotation class MainScope
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/di/FragmentKey.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation.di
2 |
3 | import androidx.fragment.app.Fragment
4 | import dagger.MapKey
5 | import kotlin.reflect.KClass
6 |
7 | @Target(
8 | AnnotationTarget.FUNCTION,
9 | AnnotationTarget.PROPERTY_GETTER,
10 | AnnotationTarget.PROPERTY_SETTER
11 | )
12 | @Retention(AnnotationRetention.RUNTIME)
13 | @MapKey
14 | annotation class FragmentKey(val value: KClass)
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/App.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation
2 |
3 | import android.app.Application
4 | import ca.nick.multimodulenavigation.di.AppComponent
5 | import ca.nick.multimodulenavigation.di.AppComponentProvider
6 | import ca.nick.multimodulenavigation.di.DaggerAppComponent
7 |
8 | @Suppress("unused")
9 | class App : Application(), AppComponentProvider {
10 |
11 | override val appComponent: AppComponent by lazy {
12 | DaggerAppComponent
13 | .factory()
14 | .application(this)
15 | }
16 | }
--------------------------------------------------------------------------------
/detail/src/main/res/layout/detail_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/di/AppComponent.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation.di
2 |
3 | import android.app.Application
4 | import dagger.BindsInstance
5 | import dagger.Component
6 | import javax.inject.Singleton
7 |
8 | @Singleton
9 | @Component(
10 | modules = [
11 | SubcomponentsModule::class
12 | ]
13 | )
14 | interface AppComponent {
15 |
16 | @Component.Factory
17 | interface Factory {
18 | fun application(@BindsInstance application: Application): AppComponent
19 | }
20 |
21 | fun mainComponentFactory(): MainComponent.Factory
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/OnItemClickedDirections.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation
2 |
3 | import androidx.fragment.app.FragmentManager
4 | import ca.nick.detail.DetailFragment
5 | import ca.nick.list.OnItemClicked
6 | import javax.inject.Inject
7 |
8 | class OnItemClickedDirections @Inject constructor(
9 | private val fragmentManager: FragmentManager
10 | ) : OnItemClicked {
11 |
12 | override fun onItemClicked() {
13 | fragmentManager.beginTransaction()
14 | .replace(R.id.container, DetailFragment())
15 | .addToBackStack(null)
16 | .commit()
17 | }
18 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/di/MainModule.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation.di
2 |
3 | import androidx.fragment.app.FragmentFactory
4 | import ca.nick.list.OnItemClicked
5 | import ca.nick.multimodulenavigation.AppFragmentFactory
6 | import ca.nick.multimodulenavigation.OnItemClickedDirections
7 | import dagger.Binds
8 | import dagger.Module
9 |
10 | @Module
11 | abstract class MainModule {
12 | @Binds
13 | abstract fun onItemClicked(onItemClickedDirections: OnItemClickedDirections): OnItemClicked
14 |
15 | @Binds
16 | abstract fun fragmentFactory(appFragmentFactory: AppFragmentFactory): FragmentFactory
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/di/MainComponent.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation.di
2 |
3 | import androidx.fragment.app.FragmentFactory
4 | import androidx.fragment.app.FragmentManager
5 | import dagger.BindsInstance
6 | import dagger.Subcomponent
7 |
8 | @MainScope
9 | @Subcomponent(
10 | modules = [
11 | MainModule::class,
12 | FragmentsModule::class
13 | ]
14 | )
15 | interface MainComponent {
16 |
17 | val fragmentFactory: FragmentFactory
18 |
19 | @Subcomponent.Factory
20 | interface Factory {
21 | fun create(@BindsInstance fragmentManager: FragmentManager): MainComponent
22 | }
23 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/di/FragmentsModule.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation.di
2 |
3 | import androidx.fragment.app.Fragment
4 | import ca.nick.detail.DetailFragment
5 | import ca.nick.list.ListFragment
6 | import dagger.Binds
7 | import dagger.Module
8 | import dagger.multibindings.IntoMap
9 |
10 | @Module
11 | abstract class FragmentsModule {
12 | @Binds
13 | @IntoMap
14 | @FragmentKey(ListFragment::class)
15 | abstract fun listFragment(listFragment: ListFragment): Fragment
16 |
17 | @Binds
18 | @IntoMap
19 | @FragmentKey(DetailFragment::class)
20 | abstract fun detailFragment(detailFragment: DetailFragment): Fragment
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/ca/nick/multimodulenavigation/AppFragmentFactory.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.multimodulenavigation
2 |
3 | import androidx.fragment.app.Fragment
4 | import androidx.fragment.app.FragmentFactory
5 | import javax.inject.Inject
6 | import javax.inject.Provider
7 |
8 | class AppFragmentFactory @Inject constructor(
9 | private val fragments: Map, @JvmSuppressWildcards Provider>
10 | ) : FragmentFactory() {
11 |
12 | override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
13 | val fragmentClass: Class = loadFragmentClass(classLoader, className)
14 | return fragments[fragmentClass]?.get() ?: super.instantiate(classLoader, className)
15 | }
16 | }
--------------------------------------------------------------------------------
/list/src/main/java/ca/nick/list/ListFragment.kt:
--------------------------------------------------------------------------------
1 | package ca.nick.list
2 |
3 | import android.os.Bundle
4 | import android.view.View
5 | import android.widget.Button
6 | import androidx.fragment.app.Fragment
7 | import javax.inject.Inject
8 |
9 | class ListFragment @Inject constructor(
10 | private val onItemClicked: OnItemClicked,
11 | @Suppress("unused")
12 | private val someHeavyWeightDependency: SomeHeavyWeightDependency
13 | ) : Fragment(R.layout.list_fragment) {
14 |
15 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
16 | super.onViewCreated(view, savedInstanceState)
17 | view.findViewById