1 of 9

Android + Gradle Modules + Navigation + FragmentFactory + Fragment constructor injection

2 of 9

App structure

  • Application module (androidTests, flavors)
  • Navigation module (includes nested navigation graph, setup single activity)
  • Feature modules (define nested graph, define fragments)

3 of 9

Jetpack Navigation library

  • Single activity
  • Works with fragments
  • Supports nested graphs

4 of 9

Fragment

  • Fragment is dummy view for showing restricted states (normal, empty, error ViewStates)
  • ViewModel provider is injected in Fragment constructor
  • Without business logic (it is ViewModel responsibility)
  • Without argument handling (it is FragmentFactory responsibility)
  • Fragment is android testable and screenshot testable

5 of 9

FragmentFactory

  • FragmentFactory creates Fragment
  • Default Fragment constructor

@NonNull

public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) {

try {

Class<? extends Fragment> cls = loadFragmentClass(classLoader, className);

return cls.getConstructor().newInstance();

} catch (e) { ... }

}

6 of 9

Dagger and FragmentFactory

class DaggerFragmentFactory(

private val providers: MutableMap<Class<out Fragment>, Provider<Fragment>>

) : FragmentFactory() {

override fun instantiate(

classLoader: ClassLoader,

className: String

): Fragment {

val fragmentClass = loadFragmentClass(classLoader, className)

val fragment = providers[fragmentClass]?.get()

return requireNotNull(fragment)

}

}

7 of 9

Dagger component

@Component(modules = [...])

interface FeatureComponent {

fun provideFragmentFactory(): Provider<FragmentFactory>

@Component.Factory

interface Factory {

fun create(@BindsInstance ...): FeatureComponent

}

}

8 of 9

DelegateFragmentFactory

class DelegateFragmentFactory(

private val providers: List<() -> FragmentFactory>

) : FragmentFactory() {

override fun instantiate(classLoader: ClassLoader, className: String): Fragment {

for (provider in providers) {

try {

return provider.invoke().instantiate(classLoader, className)

} catch (e: Exception) {

// do nothing

}

}

return super.instantiate(classLoader, className)

}

}

9 of 9

Application and Activities

  • Application.registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks)
  • ActivityLifecycleCallbacks.onActivityCreated(Activity, Bundle?)
  • FragmentActivity.supportFragmentManager.fragmentFactory = DelegateFragmentFactory()