简体   繁体   中英

I can't inject fragment viewmodel with Hilt

I'm trying to inject the viewmodel to the Fragment using hilt, for that I created two modules one for my network component and another for the characters viewmodel.

The network module is installed in SingletonComponent and I need that the characters module installs in the FragmentComponent to get the Viewmodel through "by viewmodels()"

My activity and my fragment are annotated with "@AndroidEntryPoint" and my Application is annotated with "@HiltAndroidApp" my modules are:

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

    @Singleton
    @Provides
    fun provideLoggingInterceptor(): HttpLoggingInterceptor {
        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        return loggingInterceptor
    }

    @Singleton
    @Provides
    fun provideAuthorizationInterceptor(): AuthorizationInterceptor =
        AuthorizationInterceptor()

    @Singleton
    @Provides
    fun provideInterceptors(
        loggingInterceptor: HttpLoggingInterceptor,
        authorizationInterceptor: AuthorizationInterceptor
    ): HttpInterceptors = HttpInterceptors(
        listOf(
            loggingInterceptor,
            authorizationInterceptor
        )
    )

    @Singleton
    @Provides
    fun provideTimeouts(): HttpTimeouts = HttpTimeouts()

    @Singleton
    @Provides
    fun provideHttpClient(
        timeouts: HttpTimeouts,
        interceptors: HttpInterceptors
    ): HttpBuilderFactory = HttpClientBuilderFactory(timeouts, interceptors)

    @Singleton
    @Provides
    fun provideGsonConverter(): GsonFactory = GsonBuilderFactory()

    @Singleton
    @Provides
    fun provideHttpServiceProvider(
        httpBuilderFactory: HttpBuilderFactory,
        gsonFactory: GsonFactory
    ): HttpProvider = HttpServiceProvider(httpBuilderFactory, gsonFactory)
}
@Module
@InstallIn(FragmentComponent::class)
class CharacterListModule {

    @Singleton
    @Provides
    fun provideCharacterMapper(): Mapper<CharacterDataContainer, PaginatedCharacters> =
        PaginatedCharactersMapper()

    @Singleton
    @Provides
    fun provideCharacterServices(
        httpServiceProvider: HttpProvider
    ): CharacterServices = httpServiceProvider.createService(CharacterServices::class.java)

    @Singleton
    @Provides
    fun provideCharacterListRemoteSource(
        characterServices: CharacterServices,
        characterMapper: Mapper<CharacterDataContainer, PaginatedCharacters>
    ): CharacterListSource = CharacterListRemoteSourceImpl(
        characterServices,
        characterMapper
    )

    @Singleton
    @Provides
    fun provideCharacterListRepository(
        characterListRemoteSource: CharacterListSource
    ): CharacterListRepository = CharacterListRepositoryImpl(
        characterListRemoteSource
    )

    @Singleton
    @Provides
    fun provideCoroutineDispatcher() = Dispatchers.IO

    @Singleton
    @Provides
    fun provideCharacterListUseCase(
        coroutineDispatcher: CoroutineDispatcher,
        characterListRepository: CharacterListRepository
    ) = CharacterListUseCase(
        coroutineDispatcher,
        characterListRepository
    )

    @Singleton
    @Provides
    fun provideCharacterUIMapper(): Mapper<Character, CharacterUI> = CharacterUIMapper()
}

and my viewmodel is:

@HiltViewModel
class CharacterListViewModel @Inject constructor(
    private val characterListUseCase: CharacterListUseCase,
    private val characterUIMapper: Mapper<Character, CharacterUI>
) : ViewModel() {

Also when I use SingletonComponent in both cases the application runs fine, but when try to use FragmentComponent fails:

在此处输入图像描述

在此处输入图像描述

Finally my dependencies are:

    object Hilt {

        internal object Versions {
            const val hilt = "2.33-beta"
            const val hiltViewModel = "1.0.0-alpha01"
        }

        const val hilt = "com.google.dagger:hilt-android:${Versions.hilt}"
        const val hiltCompiler = "com.google.dagger:hilt-android-compiler:${Versions.hilt}"
        const val hiltViewModel = "androidx.hilt:hilt-lifecycle-viewmodel:${Versions.hiltViewModel}"
        const val hiltViewModelCompiler = "androidx.hilt:hilt-compiler:${Versions.hiltViewModel}"
    }

As it names says "FragmentComponent"(s) only live as long as it fragments does. You can't inject something that is fragment scoped into a view model, because viewmodels outlive its fragments lifecycle.. Change "FragmentScoped" with "SingletonScoped".

Please read the official documentation first before working with scopes. 99% of the time, using a "SingletonComponent" is more than enough

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM