Is there a way in Hilt that I can achieve the belo...
# dagger
g
Is there a way in Hilt that I can achieve the below without having the Manager as Singleton?
Copy code
interface ManagerProxy {
    fun execute()
}

class Manager() : ManagerProxy {

    override fun execute() { // do something }

    fun otherExecute() { // do something else }
}

class ClientOne @Inject constructor(
    private val manager: Manager 
) { 
    mananager.otherExecute()
    ...
}

class ClientTwo @Inject constructor(
   private val managerProxy: ManagerProxy // need to have the same instance of Manager from ClientOne
) {
    mananager.execute()
    ...
}
I was trying with the following but it doesn't work
Copy code
@Module
@InstallIn(SingletonComponent::class)
object ApplicationModule {

    @Provides
    @Named("MyManager")
    fun provideMyManager(
        someRepository: SomeRepository
    ): Manager {
        return Manager(someRepository)
    }

}

@Module
@InstallIn(SingletonComponent::class)
interface ManagerModule {

    @Binds
    fun bindManagerProxy(
        @Named("MyManager") manager: Manager
    ): ManagerProxy
}
the ClientManager becomes
Copy code
class Manager @Inject constructor() : ManagerProxy {

    override fun execute() { // do something }

    fun otherExecute() { // do something else }
}
and then in the ClientOne
Copy code
class ClientOne @Inject constructor(
    @Named("MyManager") private val manager: Manager // named parameter
) { ... }
n
It needs some sort of scope. Since you're using hilt you could use a smaller scope like
@ActivityScoped
or
@ViewModelScoped
to avoid making it a singleton
g
hi @Nicholas Doglio thank you for your reply. where exactly I need the scope?
n
I'm on Mobile so apologies for sudo code but you don't need
ApplicationModule
at all You can just update
Manager
to look like this
Copy code
@Singleton // or other scope like @ActivityScoped
class Manager @Inject constructor() : ManagerProxy
g
no worries and thank you again for the quick response. I don't really want
Manager
as Singleton or ActivityScoped. ViewModelScoped is my goal but still doesn't work if I do something like this:
Copy code
@Module
@InstallIn(ViewModelComponent::class)
interface ManagerModule {

    @Binds
    @ViewModelScoped
    fun bindManagerProxy(
        @Named("MyManager") manager: Manager
    ): ManagerProxy
}

@ViewModelScoped
class Manager @Inject constructor() : ManagerProxy
then the ClientOne and ClientTwo won't have the same instance of the
Manager
class
Copy code
@ViewModelScoped
class ClientOne @Inject constructor(
    private val manager: Manager 
) {}

@ViewModelScoped
class ClientTwo @Inject constructor(
   private val managerProxy: ManagerProxy
) {}
n
@ViewModelScoped
only works if they're being accessed by the same ViewModel, if they're being accessed by separate screens or separate parts of your app you'll either need a different broader scope. You could also look into defining a custom scope
g
yup that's true. I am just surprised it didn't work with
@Named
with my very first try
n
@Named
is a qualifier and is better when you when separate implementations but don’t care about any of them being retained/singletons
Copy code
@Module
@InstallIn(SingletonComponent::class)
object ApplicationModule {

    @Provides
    @Named("loggedIn")
    fun provideLoggedInMyManager(
        loggedInRepository: Repository
    ): Manager {
        return Manager(loggedInRepository)
    }

    @Provides
    @Named("loggedOut")
    fun provideLoggedOutMyManager(
        loggedOutRepository: Repository
    ): Manager {
        return Manager(loggedOutRepository)
    }
}
With the above you can have separate implementations of
Manager
that take different versions of the
Repository
that could have changes in behavior based on logged in state.