13

How can I translate something like this:

@Module
abstract class BaseActivityModule<A : AppCompatActivity> {
    @Binds
    abstract fun provideActivity(activity: A): AppCompatActivity

    companion object {
        @Provides
        @ActivityContext
        fun provideContext(activity: AppCompatActivity): Context = activity
    }
}

@Module
abstract class SomeActivityModule : BaseActivityModule<SomeActivity>()

So it can be used latter like:

@ActivityScope
class UtilsClass @Inject constructor(
    private val activity: AppCompatActivity,
    ...
){...}

I've migrated a playground project from dagger to hilt and it went super smooth, but I've stumbled across this use-case. I've changed the code so I wont be needing that instance any more but the curiosity remains.

Is it even possible now that we don't need this kind of setup:

@ActivityScope
@ContributesAndroidInjector(modules = [SomeActivityModule::class])
abstract fun someActivity(): SomeActivity
GuilhE
  • 11,591
  • 16
  • 75
  • 116

5 Answers5

10

i didn't try this code yet, if its not working please CMiMW,
according to documentation here, you can use predefined qualifers for Application Context and activity context.

your code may look like this

@ActivityScoped
class UtilsClass @Inject constructor(
@ActivityContext private val activity: Context,
... 
){
 ...
 val myActivity = if(context is MyActivity) context as MyActivity else throw ......  // check if its provided context was desired activity
 ...

}
daya pangestu
  • 400
  • 3
  • 12
5

Yes, you can cast @ActivityContext to that of your activity, read on for more clarification.
@ActivityContext can be used to scope the bindings that require activity context. But similar to dagger scoping scheme, you can only scope in classes that are @ActivityScoped, i.e if you try @ActivityContext in a class and scope it with any other scope wider than @ActivityScoped, you will face compile time error

@dagger.hilt.android.qualifiers.ActivityContext android.content.Context cannot be provided without an @Provides-annotated method

Moreover, new bindings objects will instantiated every time any new activity is created.
refer https://developer.android.com/training/dependency-injection/hilt-android#component-scopes

Raja Singla
  • 136
  • 1
  • 2
5

Just cast/get activity from context. But you can also specify class according to the docs

tailrec fun Context?.activity(): Activity? = this as? Activity
    ?: (this as? ContextWrapper)?.baseContext?.activity()

class MyClass @Inject constructor(@ActivityContext context: Context) {

    init {
        val activity = context.activity() as Activity
    }

    //...
}
Vlad
  • 7,997
  • 3
  • 56
  • 43
1

I was facing situation while working on project, thought I would share if this helps someone.

The activity Context binding is available using @ActivityContext

class PaymentService @Inject constructor(
    @ActivityContext context: Context
) { ... }

and Activity binding is available without qualifiers.

class PaymentService @Inject constructor(
    activity: FragmentActivity
) { ... }
Hussain
  • 1,243
  • 12
  • 21
0

Yes, We don't need this kind of setup. We just have to provide @AndroidEntryPoint on our activities and Hilt will handle the dependency injections on its own. Also with Hilt, There is no need to write Factory and InjectorComponents.

RatneZ
  • 1,078
  • 9
  • 9
  • 1
    Hello RatneZ, yup I know and that's pretty cool, but I was wondering if with Hilt it's possible to provide an Activity instance, and if so, how? I don't have a use-case for it, just curiosity, because with Dagger you can and Hilt uses Dagger under the hood. – GuilhE Jun 18 '20 at 08:36
  • 1
    Hey Guilhe, you can refer this answer for that https://stackoverflow.com/a/62538522/5815842 – RatneZ Sep 26 '20 at 15:54