Interfejsy API zakresu ViewModel (widoki), część Androida Jetpack.

Pojęcia i implementacja w Jetpack Compose

Zakres jest kluczowy dla skutecznego korzystania z obiektów ViewModel. Każdy obiekt ViewModel jest ograniczony do obiektu, który implementuje interfejs ViewModelStoreOwner. Istnieje kilka interfejsów API, które ułatwiają zarządzanie zakresem obiektów ViewModel.

Metoda ViewModelProvider.get() pozwala uzyskać instancję ViewModel w zakresie dowolnego ViewModelStoreOwner. Użytkownicy języka Kotlin mają do dyspozycji różne funkcje rozszerzające, które można wykorzystać w najczęstszych przypadkach użycia. Wszystkie implementacje funkcji rozszerzających Kotlin korzystają wewnętrznie z interfejsu ViewModelProvider API.

Obiekty ViewModel powiązane z najbliższym obiektem ViewModelStoreOwner

Model widoku możesz ograniczyć do aktywności, fragmentu lub miejsca docelowego w grafie nawigacji. Funkcje rozszerzeń viewModels() udostępniane przez biblioteki Activity, Fragment i Navigation umożliwiają uzyskanie instancji ViewModela w zakresie 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);
}

Obiekty ViewModel powiązane z dowolnym obiektem ViewModelStoreOwner

Funkcje ComponentActivity.viewModels()Fragment.viewModels() w systemie View przyjmują opcjonalny parametr ownerProducer, za pomocą którego możesz określić, do którego ViewModelStoreOwner jest przypisana instancja ViewModel. Poniższy przykład pokazuje, jak uzyskać instancję ViewModel w zakresie 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);
    }
}

Pobieranie obiektu ViewModel o zakresie działania obejmującym aktywność z fragmentu jest częstym przypadkiem użycia. Możesz to zrobić za pomocą funkcji rozszerzenia activityViewModels() Wyświetlenia. Jeśli nie używasz widoków i języka Kotlin, możesz używać tych samych interfejsów API, przekazując odpowiedniego właściciela.

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

Obiekty ViewModel w zakresie wykresu nawigacji

Wykresy nawigacji są też właścicielami pamięci ViewModel. Jeśli używasz Navigation Fragment, możesz uzyskać instancję ViewModela w zakresie wykresu nawigacji za pomocą funkcji rozszerzenia navGraphViewModels(graphId) Views.

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

Jeśli oprócz biblioteki Jetpack Navigation używasz Hilt, możesz użyć interfejsu API hiltNavGraphViewModels(graphId) w ten 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);
    }
}