ViewModel Scoping API Android Jetpack의 구성요소
범위는 ViewModel을 효과적으로 사용하기 위한 핵심입니다. 각 ViewModel의 범위는 ViewModelStoreOwner
인터페이스를 구현하는 객체로 지정됩니다. 몇 가지 API를 사용하면 ViewModel의 범위를 더 쉽게 관리할 수 있습니다.
이 문서에서는 알아야 할 주요 기법을 간략히 설명합니다.
ViewModelProvider.get()
메서드를 사용하면 ViewModelStoreOwner
로 범위가 지정된 ViewModel의 인스턴스를 가져올 수 있습니다. Kotlin 사용자의 경우 가장 일반적인 사용 사례에 다양한 확장 함수를 사용할 수 있습니다. 모든 Kotlin 확장 함수 구현은 내부적으로 ViewModelProvider API를 사용합니다.
가장 가까운 ViewModelStoreOwner로 ViewModel 범위 지정
탐색 그래프의 활동, 프래그먼트 또는 대상으로 ViewModel의 범위를 지정할 수 있습니다. 활동, 프래그먼트, 탐색 라이브러리에서 제공하는 viewModels()
확장 함수와 Compose의 viewModel()
함수를 사용하면 가장 가까운 ViewModelStoreOwner
로 범위가 지정된 ViewModel 인스턴스를 가져올 수 있습니다.
뷰
import androidx.activity.viewModels class MyActivity : AppCompatActivity() { // ViewModel API available in activity.activity-ktx // The ViewModel is scoped to `this` Activity val viewModel: MyViewModel by viewModels() } import androidx.fragment.app.viewModels class MyFragment : Fragment() { // ViewModel API available in fragment.fragment-ktx // The ViewModel is scoped to `this` Fragment val viewModel: MyViewModel by viewModels() }
뷰
import androidx.lifecycle.ViewModelProvider; public class MyActivity extends AppCompatActivity { // The ViewModel is scoped to `this` Activity MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class); } public class MyFragment extends Fragment { // The ViewModel is scoped to `this` Fragment MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class); }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( modifier: Modifier = Modifier, // ViewModel API available in lifecycle.lifecycle-viewmodel-compose // The ViewModel is scoped to the closest ViewModelStoreOwner provided // via the LocalViewModelStoreOwner CompositionLocal. In order of proximity, // this could be the destination of a Navigation graph, the host Fragment, // or the host Activity. viewModel: MyViewModel = viewModel() ) { /* ... */ }
ViewModelStoreOwner로 범위가 지정된 ViewModel
뷰 시스템의 ComponentActivity.viewModels()
및 Fragment.viewModels()
함수와 Compose의 viewModel()
함수는 ownerProducer
매개변수를 선택적으로 사용합니다. 개발자는 이 매개변수를 사용하여 ViewModel 인스턴스의 범위로 지정할 ViewModelStoreOwner
를 지정할 수 있습니다.
다음 샘플은 상위 프래그먼트로 범위가 지정된 ViewModel의 인스턴스를 가져오는 방법을 보여줍니다.
뷰
import androidx.fragment.app.viewModels class MyFragment : Fragment() { // ViewModel API available in fragment.fragment-ktx // The ViewModel is scoped to the parent of `this` Fragment val viewModel: SharedViewModel by viewModels( ownerProducer = { requireParentFragment() } ) }
뷰
import androidx.lifecycle.ViewModelProvider; public class MyFragment extends Fragment { SharedViewModel viewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { // The ViewModel is scoped to the parent of `this` Fragment viewModel = new ViewModelProvider(requireParentFragment()) .get(SharedViewModel.class); } }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( context: Context = LocalContext.current, // ViewModel API available in lifecycle.lifecycle-viewmodel-compose // The ViewModel is scoped to the parent of the host Fragment // where this composable function is called viewModel: SharedViewModel = viewModel( viewModelStoreOwner = (context as Fragment).requireParentFragment() ) ) { /* ... */ }
프래그먼트에서 활동 범위 ViewModel을 가져오는 것은 일반적인 사용 사례입니다. 날짜
이렇게 하려면 activityViewModels()
뷰 확장 함수를 사용할 수 있습니다. 뷰와 Kotlin을 사용하지 않는 경우 올바른 소유자를 전달하여 위와 동일한 API를 사용할 수 있습니다.
뷰
import androidx.fragment.app.activityViewModels class MyFragment : Fragment() { // ViewModel API available in fragment.fragment-ktx // The ViewModel is scoped to the host Activity val viewModel: SharedViewModel by activityViewModels() }
뷰
import androidx.lifecycle.ViewModelProvider; public class MyFragment extends Fragment { SharedViewModel viewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { // The ViewModel is scoped to the host Activity viewModel = new ViewModelProvider(requireActivity()) .get(SharedViewModel.class); } }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( context: Context = LocalContext.current, // ViewModel API available in lifecycle.lifecycle-viewmodel-compose // The ViewModel is scoped to the Activity of the host Fragment // where this composable function is called viewModel: SharedViewModel = viewModel( viewModelStoreOwner = (context as Fragment).requireActivity() ) ) { /* ... */ }
탐색 그래프로 범위가 지정된 ViewModel
탐색 그래프도 ViewModel 스토어 소유자입니다. Navigation Fragment 또는 Navigation Compose를 사용하는 경우 navGraphViewModels(graphId)
뷰 확장 함수를 사용하여 탐색 그래프로 범위가 지정된 ViewModel 인스턴스를 가져올 수 있습니다.
뷰
import androidx.navigation.navGraphViewModels class MyFragment : Fragment() { // ViewModel API available in navigation.navigation-fragment // The ViewModel is scoped to the `nav_graph` Navigation graph val viewModel: SharedViewModel by navGraphViewModels(R.id.nav_graph) // Equivalent navGraphViewModels code using the viewModels API val viewModel: SharedViewModel by viewModels( { findNavController().getBackStackEntry(R.id.nav_graph) } ) }
뷰
import androidx.lifecycle.ViewModelProvider; public class MyFragment extends Fragment { SharedViewModel viewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { NavController navController = NavHostFragment.findNavController(this); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph); // The ViewModel is scoped to the `nav_graph` Navigation graph viewModel = new ViewModelProvider(backStackEntry).get(SharedViewModel.class); } }
Compose
import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyAppNavHost() { // ... composable("myScreen") { backStackEntry -> // Retrieve the NavBackStackEntry of "parentNavigationRoute" val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("parentNavigationRoute") } // Get the ViewModel scoped to the `parentNavigationRoute` Nav graph val parentViewModel: SharedViewModel = viewModel(parentEntry) // ... } }
Jetpack Navigation과 함께 Hilt를 사용하는 경우 다음과 같이 hiltNavGraphViewModels(graphId)
API를 사용할 수 있습니다.
뷰
import androidx.hilt.navigation.fragment.hiltNavGraphViewModels class MyFragment : Fragment() { // ViewModel API available in hilt.hilt-navigation-fragment // The ViewModel is scoped to the `nav_graph` Navigation graph // and is provided using the Hilt-generated ViewModel factory val viewModel: SharedViewModel by hiltNavGraphViewModels(R.id.nav_graph) }
뷰
import androidx.hilt.navigation.HiltViewModelFactory; import androidx.lifecycle.ViewModelProvider; public class MyFragment extends Fragment { SharedViewModel viewModel; @Override public void onViewCreated(View view, Bundle savedInstanceState) { NavController navController = NavHostFragment.findNavController(this); NavBackStackEntry backStackEntry = navController.getBackStackEntry(R.id.my_graph); // The ViewModel is scoped to the `nav_graph` Navigation graph // and is provided using the Hilt-generated ViewModel factory viewModel = new ViewModelProvider( backStackEntry, HiltViewModelFactory.create(getContext(), backStackEntry) ).get(SharedViewModel.class); } }
Compose
import androidx.hilt.navigation.compose.hiltViewModel @Composable fun MyAppNavHost() { // ... composable("myScreen") { backStackEntry -> val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("parentNavigationRoute") } // ViewModel API available in hilt.hilt-navigation-compose // The ViewModel is scoped to the `parentNavigationRoute` Navigation graph // and is provided using the Hilt-generated ViewModel factory val parentViewModel: SharedViewModel = hiltViewModel(parentEntry) // ... } }
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- 레이아웃 및 바인딩 표현식
- ViewModel 개요