Estoy tratando de entender HILT y estoy creando un proyecto de muestra, estoy acostumbrado a crear módulos y componentes, pero ahora con una empuñadura, está InstallIn() y tal vez tenga que jugar con ellos para hacer lo mismo que antes de. Por ejemplo, estoy acostumbrado a crear un módulo por característica como:
LoginModule (contiene: ViewModel, actividad/fragmento, fuente de datos, caso de uso, etc...) ProductModule (contiene: ViewModel, actividad/fragmento, fuente de datos, caso de uso, etc...)
A partir de ahora, he creado un NetworkModule con empuñadura:
@Module @InstallIn(ApplicationComponent::class) object NetworkModule { @Provides fun provideRetrofit(httpClient: OkHttpClient): Retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .client(httpClient) .build() @Provides fun provideOkHttpClient( httpLoggingInterceptor: HttpLoggingInterceptor, @ErrorInterceptorOkHttpClient errorInterceptor: Interceptor, ): OkHttpClient = OkHttpClient() .newBuilder() .addInterceptor(httpLoggingInterceptor) .addInterceptor(errorInterceptor) .build() @ErrorInterceptorOkHttpClient @Provides fun provideErrorInterceptor(): Interceptor = ErrorInterceptor() @Provides fun provideHttpLogginInterceptor(): HttpLoggingInterceptor { val loggingInterceptor = HttpLoggingInterceptor() loggingInterceptor.level = when { BuildConfig.DEBUG -> HttpLoggingInterceptor.Level.BODY else -> HttpLoggingInterceptor.Level.NONE } return loggingInterceptor } @Provides fun provideMyService(retrofit: Retrofit): MyService = retrofit.create(MyService::class.java) }Y luego tengo la función o digamos parte de la aplicación que es el hogar donde quiero mostrar algunas cosas a partir de ahora una Lista, y he creado esto:
@Module @InstallIn(FragmentComponent::class) object MainActivityModule { @Provides fun proviceDataSource( myService: MyService, myMapper: MyMapper, ): MyDatasource = MyDatasourceImpl(myService, myMapper) @Provides fun provicesMyMapper(): MyMapper = MapperImpl() }Y en mi Actividad, he agregado el
@AndroidEntryPoint class MainActivity : AppCompatActivity() {Y en Fragment, no tengo nada, ¿tal vez esto es lo que estoy haciendo mal?
¿Y cuándo usar ApplicationComponent SingletonComponent , etc.? Como estaba usando dagger (no dagger-android), tenía un ComponentFactory donde tenía todos estos componentes como (LoginComponent, GoogleMapComponent, ReferalCodeComponent), todos eran una característica (hablando de un proyecto de varios módulos) y allí estaba creando el fábrica de estos componentes, ¿cómo es la forma de hacer esto ahora con Hilt?
Cuando uso varios módulos, si sigo mi idea, definiré varios módulos en una biblioteca y los proporcionaré al módulo de interfaz para su uso.
Su pregunta es cómo usar el método de fábrica que definió en el módulo de interfaz. No entiendo muy bien tu pregunta sobre este punto.
Si usa la arquitectura MVVM, puede inyectar estos componentes en ViewModel. Se puede acceder al flujo proporcionado por estos componentes (como LoginComponent) en ViewModel. Por supuesto, los parámetros inyectados a través de ViewModel también pueden acceder fácilmente a los métodos correspondientes de los componentes que proporciona.
A continuación se muestra el modelo de vista en mi demostración:
@HiltViewModel class NickNameViewModel @Inject constructor( private val repo: DataRepo, application: Application, ): AndroidViewModel(application) { fun updateUserNickName( userId: String, userKey: String, userNickName: String, resultCallBack: (Boolean, String) -> Unit = {_, _ -> }, ) { viewModelScope.launch { repo.updateUserInfo( userId = userId, userKey = userKey, userNickName = userNickName, ).collect { //..... } } } } }En el ViewModel anterior, el componente DetaRepo se inyecta en el ViewModel a través de la inyección de construcción.
Se puede acceder fácilmente al método provisto en DataRepo en el método updateUserNickName.
A continuación se muestra el código de ViewModel en Fragmento:
@AndroidEntryPoint class NickNameModifyFragment: Fragment(R.layout.nick_name_modify_fragment) { companion object { const val nickNickNameResult = "nickNickNameResult" } private var _binding: NickNameModifyFragmentBinding? = null private val viewModel by viewModels<NickNameViewModel>() }Cabe señalar que si Hilt está en ViewModel de Fragment, aún debe agregar la anotación @AndroidEntryPoint a la actividad adjunta.
Espero traerte buena suerte.
Si usa SingletonComponent, entonces con la anotación @Provides también debería usar la anotación @singleton
@Module @InstallIn(SingletonComponent::class) object AppModule { @Singleton @Provides fun provideServiceGenerator( context: Context ) = ServiceGenerator(context) }De manera similar, para FragmentComponent necesita anotar con @Provides @FragmentScoped
como leí, mencionó UseCase y otras cosas, debe consultar hilt viewModel porque generará automáticamente una gran cantidad de código repetitivo para usted y manejará la dependencia de acuerdo con la actividad o el ciclo de vida del fragmento
@Module @InstallIn(ViewModelComponent::class) object ViewModelModule { //repo @Provides @ViewModelScoped fun providesTicketsRepo( checkOutApi: CheckOutApi )= TicketsRepo(checkOutApi) } @HiltViewModel class TicketsAndCouponViewModel @Inject constructor( val ticketsRepo: TicketsRepo ) : ViewModel() { /****/}fragmento interior y actividad
val viewModel by viewModels<TicketsAndCouponViewModel>()