Dagger Hilt Extensions
Build Configuration
Kotlin
dependencies {
implementation("com.google.dagger:hilt-android:2.51.1")
ksp("com.google.dagger:hilt-android-compiler:2.51.1")
implementation("it.czerwinski.android.hilt:hilt-extensions:[VERSION]")
ksp("it.czerwinski.android.hilt:hilt-processor-ksp:[VERSION]")
}
Groovy
dependencies {
implementation 'com.google.dagger:hilt-android:2.51.1'
ksp 'com.google.dagger:hilt-android-compiler:2.51.1'
implementation 'it.czerwinski.android.hilt:hilt-extensions:[VERSION]'
ksp 'it.czerwinski.android.hilt:hilt-processor-ksp:[VERSION]'
}
Property Delegation
With this library, it is possible to delegate properties to additional objects.
dagger.Lazy
val lazy: dagger.Lazy<String>
val property: String by lazy
javax.inject.Provider
val intProvider: Provider<Int>
val property: Int by intProvider
Generating Hilt Modules
@Bound and @BoundTo
Marks implementation bound to the given supertype in the given component.
@Bound annotation (added in v1.1.0) works exactly like @BoundTo annotation,
but it implicitly uses the direct supertype of the annotated class. It may only
annotate classes having exactly one direct supertype, excluding java.lang.Object.
For example:
interface Repository
@BoundTo(supertype = Repository::class)
class RepositoryA @Inject constructor() : Repository
@BoundTo(supertype = Repository::class, component = SingletonComponent::class)
@Singleton
@Named("online")
class RepositoryB @Inject constructor() : Repository
@Bound(component = SingletonComponent::class)
@Named("offline")
class RepositoryC @Inject constructor() : Repository
will generate module:
@Module
@InstallIn(SingletonComponent::class)
public interface Repository_SingletonComponent_BindingsModule {
@Binds
public fun bindRepositoryA(implementation: RepositoryA): Repository
@Binds
@Singleton
@Named("online")
public fun bindRepositoryB(implementation: RepositoryB): Repository
@Binds
@Named("offline")
public fun bindRepositoryC(implementation: RepositoryC): Repository
}
Since release 1.1.0, component property is optional, and set to
SingletonComponent by default.
@FactoryMethod
Marks factory method for the class returned by the annotated function.
For example, for a Room database:
@Database(
entities = [
User::class
],
version = 1
)
abstract class AppDatabase : RoomDatabase() {
@FactoryMethod(component = SingletonComponent::class)
@Singleton
abstract fun usersDao(): UsersDao
}
and a database factory:
interface DatabaseFactory {
@FactoryMethod(component = SingletonComponent::class)
@Singleton
fun createDatabase(): AppDatabase
}
and a database factory provider:
object DatabaseFactoryProvider {
@FactoryMethod(component = SingletonComponent::class)
fun createDatabaseFactory(
@ApplicationContext context: Context
): DatabaseFactory =
if (BuildConfig.DEBUG) TestDatabaseFactory(context)
else ProductionDatabaseFactory(context)
}
annotation processor will generate modules:
@Module
@InstallIn(SingletonComponent::class)
public object UsersDao_SingletonComponent_FactoryMethodsModule {
@Provides
@Singleton
public fun appDatabase_usersDao(factory: AppDatabase): UsersDao = factory.usersDao()
}
@Module
@InstallIn(SingletonComponent::class)
public object AppDatabase_SingletonComponent_FactoryMethodsModule {
@Provides
@Singleton
public fun databaseFactory_createDatabase(factory: DatabaseFactory): AppDatabase =
factory.createDatabase()
}
@Module
@InstallIn(SingletonComponent::class)
public object DatabaseFactory_SingletonComponent_FactoryMethodsModule {
@Provides
public fun databaseFactoryProvider_createDatabaseFactory(
@ApplicationContext context: Context
): DatabaseFactory = DatabaseFactoryProvider.INSTANCE.createDatabaseFactory(context)
}
Since release 1.1.0, component property is optional, and set to SingletonComponent by default.
@TestBound, @TestBoundTo and @TestFactoryMethod
Version 1.1.0 introduces additional test annotations that can be used to generate modules
annotated with @TestInstallIn, instead of @InstallIn:
@TestBound(instead of@Bound)@TestBoundTo(instead of@BoundTo)@TestFactoryMethod(instead of@FactoryMethod)
Test module generated using @TestBound and/or @TestBoundTo will replace the module generated using
@Bound and/or @BoundTo.
Test module generated using @TestFactoryMethod will replace the module generated with @FactoryMethod.
Hilt Testing Extensions
Build Configuration
Must be used as debugImplementation dependency to properly register EmptyFragmentActivity
in manifest.
Kotlin
dependencies {
implementation("com.google.dagger:hilt-android:2.51.1")
androidTestImplementation("androidx.test:runner:1.5.2")
debugImplementation("it.czerwinski.android.hilt:hilt-fragment-testing:[VERSION]")
}
Groovy
dependencies {
implementation 'com.google.dagger:hilt-android:2.51.1'
androidTestImplementation 'androidx.test:runner:1.5.2'
debugImplementation 'it.czerwinski.android.hilt:hilt-fragment-testing:[VERSION]'
}
Testing Fragments With Hilt
HiltFragmentScenario
Works exactly like FragmentScenario, but supports Hilt dependency injection in fragments.
Just replace androidx.fragment:fragment-testing dependency with
it.czerwinski.android.hilt:hilt-fragment-testing. All launchFragment
and launchFragmentInContainer functions are available with exactly the same signatures,
but return HiltFragmentScenario instead of FragmentScenario.
In addition, it is possible to run tests using a custom class extending FragmentActivity,
so if you are using a base activity in your project, you can run tests of your fragment in it.
HiltFragmentScenario also implements onActivity, which allows for running ActivityActions,
even when the fragment has already been removed.