Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dmytroKarataiev/e92e96d29d7224fb38895a3cb7c255db to your computer and use it in GitHub Desktop.
Save dmytroKarataiev/e92e96d29d7224fb38895a3cb7c255db to your computer and use it in GitHub Desktop.
Dagger Android 2.26 simple example with support for Singleton, PerActivity, PerFragment, and PerChildFragment scopes in Kotlin
// This is a super simplified example of how to use the dagger.android framework
// This example also shows how to scope subcomponents to higher level subcomponents:
// Activity -> Fragment -> Fragment
// It allows you to create a single instances of classes for an Activity and its Fragments.
// This example works with Dagger 2.26.
// App.kt
class App: Application(), HasAndroidInjector {
@Inject
lateinit var appDependency: AppDependency
@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Any>
override fun onCreate() {
super.onCreate()
DaggerAppComponent.create().inject(this)
}
override fun androidInjector(): AndroidInjector<Any> {
return androidInjector;
}
}
// AppModule.kt
@Module(includes = [AndroidInjectionModule::class])
abstract class AppModule {
@PerActivity
@ContributesAndroidInjector(modules = [MainActivityModule::class])
abstract fun mainActivityInjector(): MainActivity
}
// AppComponent.jkt
@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(app: App)
}
// MainActivity.kt
// Could also extend DaggerActivity instead of implementing HasAndroidInjector
class MainActivity: Activity(), HasAndroidInjector {
@Inject
lateinit var appDependency: AppDependency // same object from App
@Inject
lateinit var activityDependency: ActivityDependency
@Inject
lateinit var fragmentInjector: DispatchingAndroidInjector<Any>
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
if (savedInstanceState == null) {
addFragment(R.id.fragment_container, MainFragment())
}
}
override fun androidInjector(): AndroidInjector<Any> {
return fragmentInjector
}
private fun addFragment(@IdRes containerViewId: Int, fragment: Fragment) {
getFragmentManager.beginTransaction()
.add(containerViewId, fragment)
.commit()
}
}
// MainActivityModule.kt
@Module
abstract class MainActivityModule {
@PerFragment
@ContributesAndroidInjector(modules = [MainFragmentModule::class])
abstract fun mainFragmentInjector(): MainFragment
}
// MainFragment.kt
class MainFragment : Fragment(), HasAndroidInjector {
@Inject
lateinit var appDependency: AppDependency // same object from App
@Inject
lateinit var activityDependency: ActivityDependency // same object from MainActivity
@Inject
lateinit var fragmentDependency: FragmentDependency
@Inject
lateinit var childFragmentInjector: DispatchingAndroidInjector<Any>
fun onAttach(context: Context?) {
AndroidInjection.inject(this)
super.onAttach(context)
}
fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.main_fragment, container, false)
}
fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (savedInstanceState == null) {
addChildFragment(R.id.child_fragment_container, MainChildFragment())
}
}
override fun androidInjector(): AndroidInjector<Any> {
return childFragmentInjector
}
private fun addChildFragment(@IdRes viewId: Int, fragment: Fragment) {
getChildFragmentManager()
.beginTransaction()
.add(viewId, fragment)
.commit()
}
}
// MainFragmentModule.kt
@Module
abstract class MainFragmentModule {
@PerChildFragment
@ContributesAndroidInjector(modules = [MainChildFragmentModule::class])
abstract fun mainChildFragmentInjector(): MainChildFragment
}
// MainChildFragment.kt
class MainChildFragment : Fragment() {
@Inject
lateinit var appDependency: AppDependency // same object from App
@Inject
lateinit var activityDependency: ActivityDependency // same object from MainActivity
@Inject
lateinit var fragmentDependency: FragmentDependency // same object from MainFragment
@Inject
lateinit var childFragmentDependency: ChildFragmentDependency
fun onAttach(context: Context?) {
AndroidInjection.inject(this)
super.onAttach(context)
}
fun onCreateView(
inflater: LayoutInflater, @Nullable container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.main_child_fragment, container, false)
}
}
// MainChildFragmentModule.kt
@Module
abstract class MainChildFragmentModule {
}
// PerActivity.kt
@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class PerActivity
// PerFragment.kt
@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class PerFragment
// PerChildFragment.kt
@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class PerChildFragment
// AppDependency.kt
@Singleton
class AppDependency @Inject internal constructor()
// ActivityDependency.kt
@PerActivity
class ActivityDependency @Inject internal constructor()
// FragmentDependency.kt
@PerFragment
class FragmentDependency @Inject internal constructor()
// ChildFragmentDependency.kt
@PerChildFragment
class ChildFragmentDependency @Inject internal constructor()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment