안드로이드 앱 개발을 하다보면, 화면 회전이나 생명주기 변화에 따른 데이터 유지를 위해 ViewModel을 사용합니다. 이 때, ViewModel의 사용범위에 따라 by activityViewModels(), by viewModels(), ViewModelProvider 등 다양한 방법으로 ViewModel을 선언할 수 있습니다.
by activityViewModels()는 액티비티 범위의 ViewModel을 제공합니다. 즉, 한 액티비티 안에 여러 프래그먼트가 있다면, 이 프래그먼트들 사이에서 ViewModel을 공유할 수 있습니다.
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by activityViewModels()
...
}
위의 코드에서 by activityViewModels()를 사용하면, MainActivity와 그 안의 모든 프래그먼트에서 같은 MainViewModel 인스턴스에 접근할 수 있습니다.
by viewModels()는 프래그먼트 범위의 ViewModel을 제공합니다. 즉, 해당 프래그먼트에서만 ViewModel을 사용하게 됩니다.
class MainFragment : Fragment() {
private val viewModel: MainViewModel by viewModels()
...
}
위의 코드에서 by viewModels()를 사용하면, MainFragment에서만 MainViewModel을 사용할 수 있습니다. 다른 프래그먼트나 액티비티에서는 MainFragment의 MainViewModel에 접근할 수 없습니다.
하지만, by viewModels()를 액티비티에서 사용하는 경우에도 ViewModel의 생명주기는 해당 액티비티에 결부됩니다.
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by viewModels()
...
}
위의 코드에서 by viewModels()를 사용하면, MainActivity에서 MainViewModel을 사용할 수 있지만, 이 액티비티에 포함된 프래그먼트에서는 MainViewModel에 접근할 수 없습니다
ViewModelProvider를 사용하면 ViewModel의 인스턴스를 직접 생성하고 관리해야 합니다.
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
}
}
위의 코드에서는 viewModel = ViewModelProvider(this).get(MainViewModel::class.java) 처럼 직접 초기화해야 합니다. ViewModelProvider를 사용한 경우에는 by activityViewModels()나 by viewModels()와 달리 ViewModel의 생명주기를 개발자가 직접 관리해야 합니다. 또한, ViewModelProvider를 사용하면 ViewModel의 범위는 ViewModelProvider의 파라미터로 전달된 this의 범위에 따라 결정됩니다.