/Dagger-Hilt-Playerground

A playground for learning dagger hilt on android

Primary LanguageKotlin

Dagger Hilt

Playground for learning how to use Hilt. A new way to incorporate Dagger dependency injection into an Android application.

Examples

Below is a list of examples.

Hilt Basics

I will be making video lectures using the gists below as examples.

  1. Preparing to use Hilt
  2. Field injecting a class with no dependencies. You own that class.
  3. Scopes and the "tier-like" system
  4. Dependencies that require dependencies (Concrete classes that you own)
  5. Some things can't be constructor-injected. What is the solution?
  6. Hilt Modules, Binds and Provides
  7. Multiple Bindings of the same type

Basic MVI Repository Pattern

NOTE This is not how I would build out the architecture normally. I greatly simplified this for beginners. See Simple Network & Cache Use-case for a Clean Architecture Implementation of the same thing.

  1. Retrieve data from open-api.xyz with Retrofit
  2. Cache data with Room
  3. Display cached data in UI

Simple Network & Cache Use-case

  1. Retrieve data from open-api.xyz with Retrofit
  2. Cache data with Room
  3. Display cached data in UI

Fragment Constructor Injection with Hilt

  1. How to do fragment constructor injection with Hilt.

Instrumentation Testing

Guide:

https://developer.android.com/training/dependency-injection/hilt-testing

Important points:

  1. Dependencies
    1. Hilt
      • androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version"
      • kaptAndroidTest "com.google.dagger:hilt-android-compiler:$hilt_version"
    2. launchFragmentInContainer
      • debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
  2. Test classes
    • Annotate with @HiltAndroidTest. Example
    • Include HiltAndroidRule. Example
  3. HiltTestApplication
    • Hilt automatically generates a HiltTestAppliaction. But it requires a custom Test Runner (see next point)
  4. Custom Test Runner
  5. Field Injection
    • Requres hiltRule.inject() in @Before function of test class. Example
  6. Test Fakes
    1. Method 1: Replacing a Module
      1. Uninstall the module in the test class
        • @UninstallModules(AnalyticsModule::class). Example
      2. Create a new module within the test class that replaces the old module. Example
    2. Method 2: @BindValue
  7. Custom Application for testing
    • Guide
    • I guess you might have to do this if one of your dependencies requires your custom Application class. But I think you could probably work-around this.
  8. Multiple Test rules
    • Guide
    • I didn't know this was an issue? Never encountered this.
  9. launchFragmentInContainer
    • launchFragmentInContainer does not work with Hilt because the activity it creates is not annotated with @AndroidEntryPoint. So there is a work-around:
    • Guide
    • launchFragmentInHiltContainer work-around:
      1. Create HiltExt.kt
        • NOTE One short-coming of this work-around is you cannot specify a FragmentFactory to the function. I made a slight modification so you can. That way you can do constructor injection. Modified HiltExt.kt
      2. Create /debug/HiltTestActivity.kt
      3. Create /debug/AndroidManifest.xml
      4. Launch the fragment: val scenario = launchFragmentInHiltContainer<MainFragment>( factory = fragmentFactory )

Issues

I got this weird error:

Could not determine the dependencies of task ':app:processDebugAndroidTestManifest'.
> Could not resolve all task dependencies for configuration ':app:debugAndroidTestRuntimeClasspath'.
   > Could not resolve com.google.code.findbugs:jsr305:{strictly 3.0.1}.
     Required by:
         project :app
      > Cannot find a version of 'com.google.code.findbugs:jsr305' that satisfies the version constraints: 
           Dependency path 'DaggerHiltPlayground:app:unspecified' --> 'androidx.test.espresso:espresso-core:3.2.0' --> 'com.google.code.findbugs:jsr305:2.0.1'
           Constraint path 'DaggerHiltPlayground:app:unspecified' --> 'com.google.code.findbugs:jsr305:{strictly 3.0.1}' because of the following reason: debugRuntimeClasspath uses version 3.0.1
           Dependency path 'DaggerHiltPlayground:app:unspecified' --> 'com.google.dagger:hilt-android-testing:2.28-alpha' --> 'com.google.code.findbugs:jsr305:3.0.1'
           Dependency path 'DaggerHiltPlayground:app:unspecified' --> 'com.google.dagger:hilt-android:2.28-alpha' --> 'com.google.code.findbugs:jsr305:3.0.1'
           Dependency path 'DaggerHiltPlayground:app:unspecified' --> 'com.google.dagger:hilt-android-testing:2.28-alpha' --> 'com.google.guava:guava:27.1-jre' --> 'com.google.code.findbugs:jsr305:3.0.2'

Solution

invertase/react-native-firebase#1954

I just added this to build.gradle and everything worked fine:

android {
    ... 

    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0'
    }
}