마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

힐트 너무 이해가 안갑니다

0 추천

힐트 이해가 너무 안갑니다.. 유데미 강의보면서 하고있는데

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var factory : NewsViewModelFactory
    lateinit var viewmodel : NewsViewModel
    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment
        val navController = navHostFragment.navController

        binding.bnvNews.setupWithNavController(
            navController
        )

        viewmodel = ViewModelProvider(this,factory).get(NewsViewModel::class.java)
    }
}

이렇게 메인이 있고 

@Module
@InstallIn(SingletonComponent::class)
class FactoryModule {
    @Singleton
    @Provides
    fun provideNewsViewModelFactory(
        application: Application,
        getNewsHeadlinesUseCase: GetNewsHeadlinesUseCase) : NewsViewModelFactory {
        return NewsViewModelFactory(application, getNewsHeadlinesUseCase)
    }
}

이렇게 있는데 팩토리모듈에 provideNewsViewModelFactory을 눌러보면 메인액티비티의 factory로 이동하는데 @Module이 의존성을 제공하는거고 @Inject가 의존성을 받는거로 알고있습니다만 잘 이해가 안갑니다

모듈클래스에서 리턴을 하면 저기 메인 액티비티의 factory로 리턴을 해주는건가요?

그리고 모듈클래스에 provideNewsViewModelFactory메소드의 파라미터는 어디서 받아온건가요?

 

또 이해 안가는건 지금 이 모듈이외에 A모듈과 B모듈이 있고, A모듈 메소드를 눌러서 이동하면 

B모듈로 갑니다.. 모듈에서 리턴을 했는데 왜 모듈로 가는건지 이해가 안됩니다. 형태는 똑같고 클래스만 다르구요 컴포넌트 클래스가아닌 모듈끼리 리턴을 주고받고가 된건지 모르겠어요 정말

 

수원통학러 (3,570 포인트) 님이 2021년 9월 10일 질문

1개의 답변

0 추천
그것들 또한 Hilt가 주입(Injection)해 주겠죠? 대신 파라미터에 있는 클래스들은 모듈에 등록이 되어 있거나, Hilt 어노테이션이 붙어 있어야 겠죠. 그래야 Hilt가 Inject이 가능한 클래스로 인식을 할 수 있고 다른데로 injection이 가능할테니까요. 물론 ApplicationContext, SaveStateHandle등과 같이 Hilt가 기본적으로 지원하는 클래스들이 있긴합니다만.

따라서 GetNewsHeadLinesUseCase는 아마도 constructor 앞에 @Inject가 붙어있을 겁니다. 이렇게 해 놓으면 굳이 모듈에 등록하지 않아도 (인터페이스가 아닌 클래스의 경우) Hilt가 해당 클래스타입을 만나면 Injection을 해줄 수 있습니다.

그리고 아마도 강의를 더 들으시면 나올텐데 Hilt는 ViewModelFactory 를 inject하지 않아도 알아서 내부적으로 처리를 해줍니다.

@HiltViewModel과 viewModels() extension function을 사용하면 됩니다. 아마도 위에 올리신 예제는 이 과정을 설명하기 위한 것으로 보이네요.
spark (224,800 포인트) 님이 2021년 9월 10일 답변
모듈클래스안에 있는 파라미터들을 힐트가 알아서 주입해준다는 말씀인가요?
Hilt가 빌트인으로 지원하는 클래스나 Hilt가 inject를 할 수 있도록 되어 있는 클래스(보통은 @inject 같은 Hilt 어노테이션이 붙거나 Module에 정의하거나 하겠죠) 들은 자동으로 해줍니다. Hilt는 컴파일 타임에 이 Inject에 필요한 클래스들을 분석해서 Inection이 이루어지도록 클래스들을 만들어 줍니다. 참고로 클래스간의 의존관계를 Depenency Graph라고 합니다. ㅡModule이나 어노테이션은 Dependency Graph를 구성하기 위한 방법들 중의 하나인 거죠.
아직 살짝 헷갈리는데, 그럼 @inject나 @module 같은 어노테이션을 붙이면
힐트에서 자동적으로 알맞게 의존성 주입을 해준다는거 맞나요?

또 궁금한게, @module, @provides는 의존성을 제공하고,
@component, @inject는 의존성을 받는거로 알고있는데 맞나요?
네. @Module은 모듈 안에서 injectin 할 크래스를 바인드하거나 provide해줘야하구요, @inject를 사용하면 클래스의 경우 자동으로 dpendency를 찾아서 처리해 줍니다. interface는 여전히 Module안에 바인딩을 해줘야 하구요. 한번써보면 기본적인 사용은 어려울 게 없습니다. 특별한 요구사항이 생겨서 기본적인 틀을 벗어날 때가 어렵죠.
@Component는 모듈을 필요에 따라 합쳐 놓은 개념이라고 보시면 좀 쉬울까요? 예를 들면 로그인화면이 있다면 여기에 사용될  인스턴스들을 LoginComponent 안에 집어넣어서 사용할 수가 있습니다. 로그인화면으로 scope을 제한할 때 유용하게 사용될 수 있습니다.
어노테이션들은 영어 단어 의미대로 이해하시면 될 것 같습니다. 예를 들어
@Module
object AppModule {

@Provides
@Singleton
fun provideSomethign(): Something {

}

A Module "AppModule" provides a singleton Somthing. 처럼 읽으시면 좀 더 쉬울 겁니다.

연습삼아 Hilt없이 DI 코드를 적접 만들어 보는 게 DI를 이해하는데 도움이 될 수 있습니다.
라이브러리없이 DI하는 것도 해봤는데, 라이브러리없이 하는 DI는 파라미터로 넘기지만, 힐트는 넘기는게 없는데 파라미터로 어떻게 들어가지? 생각에 너무 헷갈렸습니다.

하나 더 궁금한게 있는데,
@Module
@InstallIn(SingletonComponent::class)
class UseCaseModule {
    @Singleton
    @Provides
    fun provideNewsHeadLineUseCase(newsRepository: NewsRepository):GetNewsHeadlinesUseCase {
        return GetNewsHeadlinesUseCase(newsRepository)
    }
}
이렇게 모듈이 있고,

class GetNewsHeadlinesUseCase(private val newsRepository: NewsRepository) {
    suspend fun execute(country : String, page : Int) : Resource<ApiResponse> {
        return newsRepository.getNewsHeadlines(country,page)
    }
}

이렇게 유스케이스가 있는데 모듈은 의존성을 제공하는거고, 지금 유스케이스는
의존성을 생성자를 통해 받고 있으니 저게 동작하는 것같은데, 현재 유스케이스에 어노테이션이 아무것도 없잖아요..? 어떻게 받아지는건가요 어노테이션이 안달려있는데
이미 앞에서 말씀을 드린 내용인데요.
GetNewsHeadlinesUseCase 를 provide해주라고 UseCaseModule에 정의되어 있잖아요? UseCaseModule 에 provide할 객체를 정의를 하던가 아니면 @Inject를 붙이던가.
인터페이스는 살짝 달라요. 구현 클래스에 @Inject를 붙이더라도 @Bind를 해줘야 하구요.
...