Android발행일 2024. 11. 21.원본 https://blog.naver.com/jword_/223668364428 ↗

[Jetpack compose] hiltnavigation으로 ViewModel DI적용

[Jetpack compose] hiltnavigation으로 ViewModel DI적용 — #개발자의도구들 #androidjetapck #안드로이드개발 #hiltviewmodel #hiltnavigation 🚨📝 📖 📒✏...

#Android Studio#Naver Blog

#개발자의도구들 #androidjetapck #안드로이드개발 #hiltviewmodel #hiltnavigation

🚨📝 📖 📒✏️💡🔍

​

AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니다

\* 현재 Spring x 프로젝트를 진행하고 있습니다. 전체 목차를 보시려면 여기를 눌러주세요.

\* 해당 프로젝트 이전에 공부한 내용을 보시려면 여기를 눌러주세요.

Viemodel DI

Viewmodel은 Scrren에 주입되어야 하는데, @Inject가 아닌 생성자 parameter로 전달해야합니다. 하지만, Scrren마다 매번 Viewmodel을 선언해서 주입하기에 많이 번거롭다는 생각을 하였고, 알아서 주입될 수 있도록 하는 방법을 찾다가 HiltViewMdoel에 대해 알게되었습니다.

Index

  • Problem
  • Hilt-nav
  • Lib
  • ViewModel
  • Scrren
  • How to work?
  • Solved
  • Question
  • Answer
  • Feedback
💡 Tips

Promblem

kotlin 코드 예제
                                    class MainActivity : ComponentActivity() {
    val signUpViewModel: SignUpViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            MyApplicationTheme {
                Card(modifier = Modifier.padding(16.dp)) {
                    SignUpScreen(signUpViewModel)
                }
            }
        }
    }
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    MyApplicationTheme {
    }
}

현재 스크린 테스트를 위해 Entrypoint에서 viewMdoel을 생성하여 직접 Scrren에 주입하고 있습니다. 이 상황에서 여러가지 문제들을 고려하였습니다.

text 코드 예제
                                    1. 실제 환경에서 EntryPoint에 ViewModel()을 생성하는 것이 옳은 것인가?

2. 아니라고 한다면, viewModel은 어디에서 생성되어야 하는가?

3. 2번을 해결했다고 하면, 매번 Screen마다 viewModel을 주입하는 방법이 옳은가?

Hilt-nav

위 문제 해결을 위해 hilt-navigation 라이브러리를 사용하면 됩니다.

​

Lib

kotlin 코드 예제
                                    implementation("androidx.hilt:hilt-navigation-compose:1.0.0") // integrate Hilt and Navigation

ViewModel Class

kotlin 코드 예제
                                    import dagger.hilt.android.lifecycle.HiltViewModel

@HiltViewModel
@HiltViewModel
class TestViewModel @Inject constructor(
    private val boardRepository: BoardRepository
) : ViewModel() {

    private val _boardResults = MutableStateFlow<List<BoardResult>>(emptyList())
    val boardResults: StateFlow<List<BoardResult>> = _boardResults

    private val _error = MutableStateFlow<String?>(null)
    val error: StateFlow<String?> = _error

    fun fetchAllBoards() {
        viewModelScope.launch(Dispatchers.IO) {
            boardRepository.getAll { result ->
                result.onSuccess { boardResults ->
                    _boardResults.value = boardResults
                    _error.value = null  // Clear any previous errors
                }.onFailure { throwable ->
                    _error.value = throwable.message
                }
            }
        }
    }
}

사실 기존에 HiltViewmodel을 ViewModel에 적용하기는 했으나, 실질적으로 자동으로 DI가 돼지 않아서 의아했었습니다 .알고보니 hilt-navigaion lib와 함께 사용해야 되더군요.

​

​

Screen Class

kotlin 코드 예제
                                    @Composable
fun TestView(
    viewModel: TestViewModel = hiltViewModel()
)

Screen의 parameter에 이렇게 적용하면됩니다.

​

How to work

kotlin 코드 예제
                                    1. @HiltViewModel 선언을 통해 해당 ViewModel을 Hilt에 등록한다

2. Screen의 parameter로 viewModel을 선언하고 개별 hiltViewModel을 넣어준다.

3. Hilt가 Screen 생성시 알아서 ViewModel을 넣는다.

Solved

text 코드 예제
                                    1. 실제 환경에서 EntryPoint에 ViewModel()을 생성하는 것이 옳은 것인가?
    - scope관련해서 문제가 생긴다.

2. 아니라고 한다면, viewModel은 어디에서 생성되어야 하는가?
    - nav에서 viewModel을 개별 생성해서 넣어줄 수 있다.
    - Hilt-nav lib을 통해 ViewModel을 Hilt로 등록후 Screen에 넣어준다.

3. 2번을 해결했다고 하면, 매번 Screen마다 viewModel을 주입하는 방법이 옳은가?
    - 옳다. 하지만 귄찮다. 그래서 hiltViewModel을 사용한다.

​