Dhunju_likes_to_Learn
Dhunju_likes_to_Learn

Reputation: 1376

Using Hilt, how to inject into a class that does not have a context?

I have a class named NetworkManager. Since it is not one of the Android Components, I am using custom entry point, NetworkManagerEntryPoint with one fun that returns NetworkClient object which is what I want to inject.

Now, to inject an instance of this class using Hilt, I believe I need to use one of the Helper methods in EntryPointAccessors. But all of them requires a reference to android components. So, do I really have to pass an android component like Context to my class to inject an object using Hilt?

class NetworkManager() {

    @InstallIn(SingletonComponent::class)
    @EntryPoint
    interface NetworkManagerEntryPoint {
        fun getNetworkClient(): NetworkClient
    }

    var defaultNetworkClient: NetworkClient = EntryPointAccessors.fromApplication(
        context, // Do I have to pass a context to this class to use Hilt?
        NetworkManagerEntryPoint::class.java
    ).getNetworkClient()

    fun <R : Any> executeRequest(
            request:Request<R>,
            networkClient: NetworkClient = defaultNetworkClient
    ): Response<R> {
        // Do some operation
    }
}

Upvotes: 3

Views: 4969

Answers (2)

Dhunju_likes_to_Learn
Dhunju_likes_to_Learn

Reputation: 1376

Okay. @Zaid Zakir's answer showed me that I can inject objects via constructor parameters, if not field injection. So, the solution for me ended up looking like this.

@Singleton
class NetworkManager @Inject constructor(
    var defaultNetworkClient: NetworkClient
) {
    fun <R : Any> executeRequest(
            request:Request<R>,
            networkClient: NetworkClient = defaultNetworkClient
    ): Response<R> {
        // Do some operation
    }
}

In another class named NetworkClientModule, I have this,

@Module
@InstallIn(SingletonComponent::class)
abstract class NetworkClientModule {

    @Binds @Singleton
    abstract fun bindDefaultNetworkClient(impl: DefaultNetworkClient): NetworkClient

}

Upvotes: 0

Zaid Zakir
Zaid Zakir

Reputation: 563

Hi there maybe you can try this way i have done , i follow the mvvm pattern

My RetrofitApi

interface RetrofitApi {
@GET("endpoint")
suspend fun getApi():Response<RetrofitApiResponse>
}

My NetworkModule

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule{

@Singleton
@Provides
fun provideApi(): RetrofitApi = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(RetrofitApi::class.java)

@Singleton
@Provides
fun provideRepository(retrofitApi:RetrofitApi) : MainRepository = 
DefualtMainRepository(retrofitApi)

}

and this module gets injected in my repository

 class DefualtMainRepository @Inject constructor(
    val retrofitApi: RetrofitApi
):MainRepository {
override suspend fun getQuotes(): Resource<RetrofitApiResponse> {

        val response = retrofitApi.getApi()
        val result = response.body()
        if (response.successful){

        }
    }
   }

If you are interested i have full project in my github and even wrote a medium article explaining it, Hopefully my answer is helpful to you https://zaidzakir.medium.com/a-simple-android-app-using-mvvm-dagger-hilt-e9f45381f1bc

Upvotes: 2

Related Questions