ViewModel Scoping API (Views)   Часть Android Jetpack.

Основные понятия и реализация Jetpack Compose

Область видимости – это ключ к эффективному использованию ViewModel. Каждая модель ViewModel привязана к объекту, который реализует интерфейс ViewModelStoreOwner. Существует несколько API, которые позволяют вам более легко управлять областью действия ваших ViewModels.

Метод ViewModelProvider.get() позволяет получить экземпляр ViewModel, ограниченный любым ViewModelStoreOwner. Для пользователей Kotlin доступны различные функции расширения, которые можно применять в наиболее распространенных случаях. Все реализации функций расширения Kotlin используют ViewModelProvider API.

ViewModel, ограниченные ближайшим ViewModelStoreOwner

Вы можете ограничить область действия ViewModel объектом Activity, Fragment или пунктом назначения графа Navigation. Функции расширения viewModels(), предоставляемые библиотеками Activity, Fragment и Navigation, позволяют получить экземпляр ViewModel, ограниченный ближайшим ViewModelStoreOwner.

Просмотры

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

Просмотры

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, ограниченные любым ViewModelStoreOwner

Функции ComponentActivity.viewModels() и Fragment.viewModels() в системе View принимают необязательный параметр ownerProducer, который можно использовать, чтобы указать, к какому ViewModelStoreOwner относится экземпляр ViewModel. В следующем примере показано, как получить экземпляр ViewModel, ограниченный родительским фрагментом:

Просмотры

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

Просмотры

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

Получение ViewModel с областью действия Activity из Fragment – распространенный вариант использования. Для этого можно использовать функцию расширения activityViewModels(). Если вы не используете Views и Kotlin, вы можете использовать те же API, что и выше, передав правильного владельца.

Просмотры

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

Просмотры

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 scoped to the Navigation graph

Графы навигации также являются владельцами хранилища ViewModel. Если вы используете Navigation Fragment, то можете получить экземпляр ViewModel, ограниченный графом навигации, с помощью функции расширения Views navGraphViewModels(graphId).

Просмотры

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

Просмотры

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

Если вы используете Hilt в дополнение к Jetpack Navigation, вы можете использовать API hiltNavGraphViewModels(graphId), как показано ниже.

Просмотры

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

Просмотры

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