APIs de ViewModel Scoping (vistas)   Parte de Android Jetpack.

Conceptos y Jetpack Compose implementation

El alcance es clave para usar ViewModels de manera eficaz. El alcance de cada ViewModel se define en un objeto que implementa la interfaz ViewModelStoreOwner. Hay varias APIs que te permiten administrar el alcance de tus ViewModels con mayor facilidad.

El método ViewModelProvider.get() te permite obtener una instancia de un ViewModel cuyo alcance sea cualquier ViewModelStoreOwner. Para los usuarios de Kotlin, hay diferentes funciones de extensión disponibles con los casos de uso más comunes. Todas las implementaciones de funciones de extensión de Kotlin usan la API de ViewModelProvider de forma interna.

ViewModels con alcance para el ViewModelStoreOwner más cercano

Puedes determinar el alcance de un ViewModel según la actividad, el fragmento o el destino de un gráfico de navegación. Las viewModels() funciones de extensión que proporcionan las bibliotecas de actividades, fragmentos y navegación te permiten obtener una instancia del ViewModel con el alcance más cercano a ViewModelStoreOwner.

Vistas

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()
}

Vistas

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);
}

ViewModels con alcance para cualquier ViewModelStoreOwner

Las funciones ComponentActivity.viewModels() y Fragment.viewModels() en el sistema de vistas toman un parámetro ownerProducer opcional que puedes usar para especificar a qué ViewModelStoreOwner se limita la instancia del ViewModel. En el siguiente ejemplo, se muestra cómo obtener una instancia de un ViewModel con alcance para el fragmento superior:

Vistas

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() }
    )
}

Vistas

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);
    }
}

Obtener un ViewModel con alcance específico de la actividad a partir de un fragmento es un caso de uso común. Cuando lo hagas, puedes usar la función de extensión de activityViewModels() vistas. Si no usas Kotlin ni las vistas, puedes usar las mismas APIs que se indicaron anteriormente y pasar el propietario correcto.

Vistas

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()
}

Vistas

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);
    }
}

ViewModels con alcance para el gráfico de navegación

Los gráficos de navegación también son propietarios de ViewModelStore. Si usas Navigation Fragment, puedes obtener una instancia de un ViewModel con alcance para un gráfico de navegación con la navGraphViewModels(graphId) función de extensión de vistas.

Vistas

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) }
    )
}

Vistas

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);
    }
}

Si usas Hilt además de Jetpack Navigation, puedes usar la hiltNavGraphViewModels(graphId) API de la siguiente manera.

Vistas

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)
}

Vistas

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);
    }
}