7

I'm new to hilt. So i want to try dependency injection with hilt on my project which use MVVM architecture. The structure look like this: JsonHelper -> RemoteDataSource -> Repository -> ViewModel.

The problems occur when i try to inject my DI on RemoteDataSource and Repository since these classes are singleton class and have a private constructor. The error codes look like this

..location\RemoteDataSource.java:40: error: Dagger does not support injection into Kotlin objects
public static final class Companion {

..location\Repository.java:30: error: Dagger does not support injection into Kotlin objects
public static final class Companion {

And these are my RemoteDataSource and Repository codes, i have tried injecting it on the constructor but it says Dagger can't inject on private constructors so then i tried to inject it on the function but still didn't work

RemoteDataSource.kt

@Singleton
class RemoteDataSource private constructor(private val jsonHelper: JsonHelper) {

companion object {

    @Volatile
    private var instance: RemoteDataSource? = null

    @Inject
    fun getInstance(jsonHelper: JsonHelper): RemoteDataSource =
        instance ?: synchronized(this) {
            instance ?: RemoteDataSource(jsonHelper).apply { instance = this }
        }

}

fun getAllRemoteMovies(moviesCallback: LoadMoviesCallback) {
    moviesCallback.onAllMoviesReceived(jsonHelper.loadRemoteMovies())
}

fun getAllRemoteTVShows(tvshowCallback: LoadTVShowCallback) {
    tvshowCallback.onAllTVShowsReceived(jsonHelper.loadRemoteTVShows())
}

interface LoadMoviesCallback {
    fun onAllMoviesReceived(moviesResponses: ArrayList<MovieItem>)
}

interface LoadTVShowCallback {
    fun onAllTVShowsReceived(tvshowResponses: ArrayList<TVShowItem>)
}

}

Repository.kt

@Singleton
class Repository private constructor(private val remoteDataSource: RemoteDataSource) : DataSource {

companion object {

    @Volatile
    private var instance: Repository? = null

    @Inject
    fun getInstance(remoteDataSource: RemoteDataSource): Repository =
        instance ?: synchronized(this) {
            instance ?: Repository(remoteDataSource).apply { instance = this }
        }

}

override fun getAllRemoteMovies(): LiveData<ArrayList<MovieItem>> {
    val remoteMoviesResult = MutableLiveData<ArrayList<MovieItem>>()
    remoteDataSource.getAllRemoteMovies(object : RemoteDataSource.LoadMoviesCallback {
        override fun onAllMoviesReceived(moviesResponses: ArrayList<MovieItem>) {
            remoteMoviesResult.value = moviesResponses
        }
    })
    return remoteMoviesResult
}

override fun getAllRemoteTVShows(): LiveData<ArrayList<TVShowItem>> {
    val remoteTVShowsResult = MutableLiveData<ArrayList<TVShowItem>>()
    remoteDataSource.getAllRemoteTVShows(object : RemoteDataSource.LoadTVShowCallback {
        override fun onAllTVShowsReceived(tvshowResponses: ArrayList<TVShowItem>) {
            remoteTVShowsResult.value = tvshowResponses
        }
    })
    return remoteTVShowsResult
}

}

And this is my injection module RemoteDataSourceModule.kt

@Module
@InstallIn(ActivityComponent::class)
object RemoteDataSourceModule {

@Singleton
@Provides
fun provideJsonHelper(context: Context): JsonHelper {
    return JsonHelper(context)
}

@Singleton
@Provides
fun provideRemoteDataSource(jsonHelper: JsonHelper): RemoteDataSource {
    return RemoteDataSource.getInstance(jsonHelper)
}

@Singleton
@Provides
fun provideRepository(remoteDataSource: RemoteDataSource): Repository {
    return Repository.getInstance(remoteDataSource)
}

}

So how can i solve this problem without changing the class constructor to public?

rijamyazid
  • 251
  • 1
  • 2
  • 10

1 Answers1

17

@Singleton annotation is enough to notify that the class is a singleton class, so i just remove the companion object and changes private constructor with a public constructor so the code will look like this:

@Singleton
class RemoteDataSource @Inject constructor(private val jsonHelper: JsonHelper) {
    // Your codes
}
rijamyazid
  • 251
  • 1
  • 2
  • 10