Interfejsy API określania zakresu modeli ViewModel Część stanowiąca część Androida Jetpack.
Zakres ma kluczowe znaczenie dla efektywnego korzystania z modeli ViewModel. Każdy model ViewModel jest ograniczony do obiektu implementującego interfejs ViewModelStoreOwner
. Istnieje kilka interfejsów API, które ułatwiają zarządzanie zakresem modeli ViewModel.
Ten dokument przedstawia kluczowe techniki, które warto znać.
Metoda ViewModelProvider.get()
umożliwia uzyskanie instancji obiektu ViewModel o zakresie dowolnego typu ViewModelStoreOwner
. Użytkownicy Kotlin mogą korzystać z różnych funkcji rozszerzeń przeznaczonych do typowych zastosowań. Wszystkie implementacje funkcji rozszerzenia Kotlin używają wbudowanego interfejsu API ViewModelProvider.
Obiekty ViewModels w zakresie najbliższego obiektu ViewModelStoreOwner
Zakres modelu ViewModel możesz określić jako aktywność, fragment lub miejsce docelowe wykresu nawigacyjnego. Funkcje rozszerzenia viewModels()
udostępniane przez biblioteki aktywności, fragmentów i nawigacji oraz funkcja viewModel()
w narzędziu Compose umożliwiają pobranie instancji obiektu ViewModel ograniczonego do najbliższego ViewModelStoreOwner
.
Wyświetlenia
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() }
Wyświetlenia
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); }
Utwórz
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() ) { /* ... */ }
Obiekty ViewModels przypisane do dowolnego właściciela sklepu ViewModelStore
Funkcje ComponentActivity.viewModels()
i Fragment.viewModels()
w systemie Widok oraz funkcja viewModel()
w sekcji Tworzenie przyjmują opcjonalny parametr ownerProducer
, którego możesz użyć, aby określić, do któregoViewModelStoreOwner
zakresu jest ograniczona instancja obiektu ViewModel.
Poniższy przykład pokazuje, jak uzyskać instancję ViewModel ograniczony do fragmentu nadrzędnego:
Wyświetlenia
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() } ) }
Wyświetlenia
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); } }
Utwórz
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() ) ) { /* ... */ }
Częstym przypadkiem użycia jest model ViewModel ograniczony do aktywności z fragmentu kodu. Aby to zrobić, skorzystaj z dostępnej funkcji rozszerzenia Views (activityViewModels()
). Jeśli nie używasz widoków danych ani Kotlin, możesz użyć tych samych interfejsów API co powyżej oraz przekazać prawo własności.
Wyświetlenia
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() }
Wyświetlenia
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); } }
Utwórz
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() ) ) { /* ... */ }
Modele View dostępne do wykresu nawigacyjnego
Wykresy nawigacyjne są również właścicielami magazynów ViewModel. Jeśli korzystasz z fragmentu nawigacji lub tworzenia nawigacji, wystąpienie obiektu ViewModel ograniczone do wykresu nawigacyjnego możesz znaleźć za pomocą funkcji rozszerzenia Views navGraphViewModels(graphId)
.
Wyświetlenia
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) } ) }
Wyświetlenia
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); } }
Utwórz
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) // ... } }
Jeśli oprócz nawigacji Jetpack używasz też Hilt, możesz użyć interfejsu API hiltNavGraphViewModels(graphId)
w następujący sposób.
Wyświetlenia
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) }
Wyświetlenia
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); } }
Utwórz
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) // ... } }
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony
- Układy i wyrażenia powiązania
- Omówienie modelu ViewModel