Безопасное использование Flows в Jetpack Compose

от автора

Рекомендуемый подход подписки Flows — подписка с учетом жизненного цикла. Если вы создаете приложение Android с помощью Jetpack Compose, используйте API collectAsStateWithLifecycle для сбора потоков с учетом жизненного цикла из вашего пользовательского интерфейса. CollectAsStateWithLifecycle позволяет вашему приложению сохранять ресурсы приложения, когда они не нужны, например, когда приложение находится в фоне. Ненужное сохранение ресурсов может повлиять на работоспособность устройства пользователя. К таким ресурсам могут относиться запросы Firebase, обновления местоположения или сети, а также подключения к базе данных.

В статье будет рассмотрены различия collectAsStateWithLifecycle и collectAsState.

collectAsStateWithLifecycle

collectAsStateWithLifecycle — это composable функция, которая собирает значения из Flow и представляет последнее значение State с учетом жизненного цикла. Каждый раз, когда происходит Flow.emit, значение State.value обновляется. Это вызывает рекомпозицию каждого использования State.value в Composition.

По умолчанию collectAsStateWithLifecycle использует Lifecycle.State.STARTED для запуска и остановки сбора значений из потока. Это происходит, когда Lifecycle входит и выходит из целевого состояния. Это состояние жизненного цикла можно настроить в параметре minActiveState.

collectAsStateWithLifecycle по умолчанию отменяет подписку Flow, когда приложение находится в фоновом режиме.

collectAsStateWithLifecycle по умолчанию отменяет подписку Flow, когда приложение находится в фоновом режиме.

В следующем фрагменте показано, как использовать collectAsStateWithLifecycle для сбора поля uiState StateFlow, которое ViewModel предоставила в вашей компонуемой функции:

@Composable fun AuthorRoute(   onBackClick: () -> Unit,   modifier: Modifier = Modifier,   viewModel: AuthorViewModel = hiltViewModel() ) {   val uiState: AuthorScreenUiState by viewModel.uiState.collectAsStateWithLifecycle()    AuthorScreen(     authorState = uiState.authorState,     newsState = uiState.newsState,     modifier = modifier,     onBackClick = onBackClick,     onFollowClick = viewModel::followAuthorToggle,   ) }

Каждый раз, когда uiState AuthorViewModel эмитит новое значение AuthorScreenUiState, AuthorRoute будет рекомпозирован.Чтобы начать использовать API collectAsStateWithLifecycle в своем проекте, добавьте артефакт androidx.lifecycle.lifecycle-runtime-compose в свой проект.

dependencies {     implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.0" }

Под капотом

Под капотом реализация collectAsStateWithLifecycle использует API repeatOnLifecycle, который является рекомендуемым способом сбора потоков в Android с использованием системы View. collectAsStateWithLifecycle избавляет вас от необходимости вводить шаблонный код, показанный ниже, который также собирает потоки с учетом жизненного цикла из составной функции:

@Composable fun AuthorRoute(...) {     val lifecycle = LocalLifecycleOwner.current.lifecycle     val uiState by produceState<AuthorScreenUiState>(         initialValue = viewModel.uiState.value         key1 = lifecycle         key2 = viewModel     ) {         lifecycle.repeatOnLifecycle(state = STARTED) {             viewModel.uiState.collect { value = it }         }     }      AuthorScreen(...) }

collectAsState

Можно задаться вопросом: если collectAsStateWithLifecycle — самый безопасный способ подписки на Flow из Composable функций в Android, зачем нам теперь нужен API collectAsState? или почему бы не добавить функциональность, учитывающую жизненный цикл, в collectAsState вместо создания нового API?

Жизненный цикл компонуемой функции не зависит от платформы, на которой работает Compose. Как описано в документации Lifecycle of composables page, экземпляры Compsable функций входят в композицию, рекомпозируются 0 или более раз и покидают Composition.

Жизненный цикл экземпляра Composable функции в Composition

Жизненный цикл экземпляра Composable функции в Composition

API collectAsState следует жизненному циклу Composition. Он подписывается на Flow, когда Compsable объект входит в Composition, и прекращает сбор, когда он покидает Composition. CollectAsState — это платформенно-независимый API, который можно использовать для подписки.

Однако при использовании Compose в приложении Android жизненный цикл Android также играет важную роль в том, как следует управлять ресурсами. Даже если Compose останавливает рекомпозиции, пока приложение Android находится в фоновом режиме, collectAsState сохраняет Flow активной. Это делает невозможным освобождение ресурсов остальной частью иерархии.

Оба метода collectAsState и collectAsStateWithLifecycle имеют свое предназначение в Compose. Последний при разработке приложений Android, первый при разработке для других платформ.

Переход с collectAsState на collectAsStateWithLifecycle не вызывает никаких затруднений:

@Composable fun AuthorRoute(     onBackClick: () -> Unit,     modifier: Modifier = Modifier,     viewModel: AuthorViewModel = hiltViewModel() ) {        -   val uiState: AuthorScreenUiState by viewModel.uiState.collectAsState() +   val uiState: AuthorScreenUiState by viewModel.uiState.collectAsStateWithLifecycle()      AuthorScreen(         authorState = uiState.authorState,         newsState = uiState.newsState,         modifier = modifier,         onBackClick = onBackClick,         onFollowClick = viewModel::followAuthorToggle,     ) }

Подписка на Flow потоков с учетом жизненного цикла — рекомендуемый способ подписки на Android, чтобы другие части вашего приложения могли при необходимости высвобождать ресурсы.

Если вы создаете приложение Android с помощью Jetpack Compose, используйте для этого Composable функцию collectAsStateWithLifecycle.


ссылка на оригинал статьи https://habr.com/ru/articles/864734/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *