Search code examples
androidviewmodeldaggerdagger-hilt

Hilt: injecting application-wide repository singleton


I'm relatively new to Dagger and I just started to use Hilt. What I want is to inject an application-wide repository (meaning it needs to be the same object everywhere) into a ViewModel. The repository will be used to retrieve the user, auth token and stuff like that. This is the closest I could get:

@Module
@InstallIn(ApplicationComponent::class)
abstract class ApplicationModule {
    @Singleton
    @Binds
    abstract fun bindUserService(
        userRepository: UserRepository
    ): UserService

}

@Singleton
class UserRepository @Inject constructor(
) : UserService {
    private var _user: User? = null

    override fun getUser(): Observable<User> {
        return if (_user == null) {
            fetchUser()
        } else {
            Observable.just(_user)
        }
    }

    private fun fetchUser(): Observable<User> {
        return Observable.just(User("foo", Random.nextDouble(100.00)))
            .delay(2, TimeUnit.SECONDS)
            .doOnEach { _user = it.value }
    }
}

class ProfileViewModel @ViewModelInject constructor(
    private val userService: UserService,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    val user: MutableLiveData<User> by lazy {
        MutableLiveData<User>()
    }

    fun init() {
        userService.getUser().observeOn(AndroidSchedulers.mainThread()).subscribe { user.apply { value = it } }
    }

}

this way everything works fine, using debug I can confirm that every time the ViewModel is used the same instance of UserRepository is injected. The problem is that _user is null the second time (eg. view is destroyed and re-created) getUser() is called. I don't know if I'm doing some silly mistake on the kotlin-side or a silly mistake on the Hilt-side.

any idea what's going on?


Solution

  • In your case doOnEach call when onSuccess and onComplete it means it call 2 times, and second time it.value is null and _user asign to null again. It's not bug from Hilt

        private fun fetchUser(): Observable<User> {
            return Observable.just(User("foo", Random.nextDouble(100.00)))
                .delay(2, TimeUnit.SECONDS)
                .doOnEach { _user = it.value }
        }