APIs de escopo do ViewModel Parte do Android Jetpack.
A definição do escopo é fundamental para usar os ViewModels de maneira eficaz. Cada ViewModel tem um
objeto que implementa a interface ViewModelStoreOwner
como escopo. Existem várias
APIs que permitem gerenciar o escopo dos ViewModels com mais facilidade.
Neste documento, descrevemos algumas das principais técnicas que você precisa conhecer.
O método ViewModelProvider.get()
permite acessar uma instância de um ViewModel
com qualquer ViewModelStoreOwner
como escopo. Para usuários do Kotlin, existem diferentes
funções de extensão disponíveis para os casos de uso mais comuns. Todas as implementações
de funções de extensão do Kotlin usam a API ViewModelProvider internamente.
ViewModels com escopo para o ViewModelStoreOwner mais próximo
Você pode definir uma atividade, um fragmento ou um destino de um gráfico de navegação como
escopo de um ViewModel. As
funções de extensão de viewModels()
fornecidas pelas bibliotecas Activity, Fragment e de navegação, e a
função viewModel()
no Compose, permitem acessar uma instância do ViewModel
que tem como escopo o ViewModelStoreOwner
mais próximo.
Visualizações
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() }
Visualizações
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() ) { /* ... */ }
ViewModels com escopo para qualquer ViewModelStoreOwner
As funções ComponentActivity.viewModels()
e Fragment.viewModels()
no
sistema de visualização e a função viewModel()
no Compose usam um parâmetro
ownerProducer
opcional que pode ser usado para especificar a qual
ViewModelStoreOwner
vai o escopo da instância do ViewModel.
O exemplo abaixo mostra como receber uma instância de um ViewModel com o
fragmento pai como escopo:
Visualizações
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() } ) }
Visualizações
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() ) ) { /* ... */ }
Receber um ViewModel com escopo de atividade de um fragmento é um caso de uso comum. Quando
para fazer isso, use o activityViewModels()
A função de extensão de visualizações está disponível. Se você não estiver usando as visualizações e o Kotlin,
utilize as mesmas APIs mencionadas acima e transmita o proprietário certo.
Visualizações
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() }
Visualizações
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() ) ) { /* ... */ }
ViewModels com escopo para o gráfico de navegação
Os gráficos de navegação também são proprietários de armazenamento do ViewModel. Se você estiver usando o
fragmento de navegação ou o
Navigation Compose, pode ver uma instância de um
ViewModel com escopo para um gráfico de navegação com a função de extensão
navGraphViewModels(graphId)
de Visualizações.
Visualizações
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) } ) }
Visualizações
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) // ... } }
Caso esteja usando o Hilt, além do Jetpack Navigation, é possível usar a API
hiltNavGraphViewModels(graphId)
desta forma:
Visualizações
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) }
Visualizações
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); } }
Escrever
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) // ... } }
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Layouts e expressões de vinculação
- Visão geral do ViewModel