API ViewModel Scoping Componente di Android Jetpack.
L'ambito è fondamentale per utilizzare i ViewModel in modo efficace. Ogni ViewModel ha come ambito un oggetto che implementa l'interfaccia ViewModelStoreOwner
. Sono disponibili diverse API che ti consentono di gestire più facilmente l'ambito dei tuoi ViewModel.
Questo documento illustra alcune delle tecniche principali che dovresti conoscere.
Il metodo ViewModelProvider.get()
consente di ottenere un'istanza di un ViewModel con ambito qualsiasi ViewModelStoreOwner
. Per gli utenti di Kotlin, sono disponibili diverse
funzioni di estensione per i casi d'uso più comuni. Tutte le implementazioni delle funzioni dell'estensione Kotlin utilizzano l'API ViewModelProvider in background.
ViewModels con ambito al proprietario ViewModelStore più vicino
Puoi definire l'ambito di un ViewModel su un'attività, un frammento o una destinazione di un grafico di navigazione. Le funzioni dell'estensione viewModels()
fornite dalle librerie Attività, Frammenti e Navigazione e la funzione viewModel()
in Scrivi ti consentono di ottenere un'istanza di ViewModel con ambito al ViewModelStoreOwner
più vicino.
Visualizzazioni
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() }
Visualizzazioni
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); }
Scrivi
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() ) { /* ... */ }
ViewModels con ambito qualsiasi proprietario ViewModelStore
Le funzioni ComponentActivity.viewModels()
e Fragment.viewModels()
nel
sistema View e la funzione viewModel()
in Compose utilizzano un parametro
ownerProducer
facoltativo che puoi usare per specificare a quale
ViewModelStoreOwner
è limitato l'ambito dell'istanza di ViewModel.
Il seguente esempio mostra come ottenere un'istanza di un ViewModel con ambito al frammento padre:
Visualizzazioni
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() } ) }
Visualizzazioni
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); } }
Scrivi
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() ) ) { /* ... */ }
Ottenere un ViewModel basato sulle attività da un frammento è un caso d'uso comune. A questo scopo, utilizza la funzione dell'estensione activityViewModels()
Views disponibile. Se non usi Views e Kotlin,
puoi usare le stesse API indicate sopra e passare il proprietario giusto.
Visualizzazioni
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() }
Visualizzazioni
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); } }
Scrivi
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 ambito al grafico di navigazione
Anche i grafici di navigazione sono proprietari del negozio ViewModel. Se utilizzi Frammento di navigazione o Scrittura navigazione, puoi ottenere un'istanza di un ViewModel con ambito di un grafico di navigazione con la funzione dell'estensione Views navGraphViewModels(graphId)
.
Visualizzazioni
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) } ) }
Visualizzazioni
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); } }
Scrivi
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) // ... } }
Se utilizzi Hilt oltre a Jetpack Navigation, puoi utilizzare l'API hiltNavGraphViewModels(graphId)
come indicato di seguito.
Visualizzazioni
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) }
Visualizzazioni
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); } }
Scrivi
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) // ... } }
Consigliato per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Layout ed espressioni di associazione
- Panoramica di ViewModel