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 ActivityAction
s,
even when the fragment has already been removed.