Оптимальный способ сбора множества потоков, которые представляют состояние пользовательского интерфейса в Jetpack ComposAndroid

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Оптимальный способ сбора множества потоков, которые представляют состояние пользовательского интерфейса в Jetpack Compos

Сообщение Anonymous »

Я пытаюсь перейти на Jetpack Compose в своем приложении для Android. Мой экран содержит множество флагов, и каждый элемент должен быть виден (и начать получать данные), только если для соответствующего флага установлено значение true. Проблема в том, что я обновляю данные элемента с помощью потоков, и опасаюсь, что слишком большое количество потоков может привести к зависанию основного потока и задержке пользовательского интерфейса.
Например, мое состояние пользовательского интерфейса выглядит так: это (это всего лишь пример, мой реальный код сложнее, но проблема та же):

Код: Выделить всё

data class UiState(
val showFavoriteBlock: Boolean,
val showRecentlyVisitedBlock: Boolean,
val showMostPopularBlock: Boolean,
val showSubscriptionBlock: Boolean,
val showFriendsBlock: Boolean,
val showRelatedBlock: Boolean,
val showLatestVisitedBlock: Boolean,
// There is 10+ same flags

// And here I have content for each block which starts loading after we receive flag
val favorites: Flow[*]>,
// 10+ flows for each block
)
Сейчас у меня есть следующий код для корневой компонуемой функции

Код: Выделить всё

@Composable
fun ExampleScreen(uiState: UiState){
// We don't show screen untill all flags will be received,
// flags itself are simple Booleans. But content for them is flow

LazyColumn {
// reading flag's value doesn't force recomposition
// because it's not State and can't be changed
if(uiState.showFavoriteBlock){
item{
// we sending flow, so updates in flow right now
// cannot force recomposition of screen
FavoritesBlock(uiState.favorites)
}
}
// 10+ items for each block
...
}
}
А вот мой составной блок Недавно посещенный блок:

Код: Выделить всё

@Composable
fun RecentlyVisitedBlock(recentlyVisitedFlow: Flow) {
// recentlyVisited is State
val recentlyVisited by recentlyVisitedFlow.collectAsStateWithLifecycle()

Row {
// Here I'm reading state and this causes recomposition for all RecentlyVisitedBlock
// So recomposition happens only when we receive new data from flow
}
}
Как видите, я собираю более 10 потоков в компонуемые функции. И... это нормально?
Все примеры в кодовых лабораториях, примерах компоновки реактивных ранцев и обучающих материалах содержат около 3-4 потоков. Но реальные приложения могут иметь около 20-30 (или даже больше) потоков, которые часто отправляют данные. Работать с потоками в фоновом режиме можно, но здесь я собираю их все в пользовательском интерфейсе.
Итак, мои вопросы:
  • Можно ли иметь 10+ (или даже 20-30) потоков и собирать их независимо в компонуемые функции? Может ли это привести к проблемам с производительностью? Поскольку основной поток должен обрабатывать их все
  • Я могу объединить все потоки в один внутри UiState, а затем использовать filterIsInstance для фильтрации и отправки каждому составному элементу только его данных. В этом случае у меня все еще есть 10+ вызовов функции CollectAsState, но, по крайней мере, вместо 10+ есть только один поток. Можно ли изменять потоки в пользовательском интерфейсе? Объединяйте их, сопоставляйте, фильтруйте.
  • Я также могу изменить свой UiState и добавить поля состояния. Но в этом случае у меня будет более 10 потоков и более 10 похожих значений состояния. Похоже на плохой шаблон.
  • Что, если я изменю свой экран на exampleScreen(uiState: Flow). В данном случае у меня есть только один поток с единственным вызовом CollectAsStateWithLifecycle, но при каждом изменении это будет вызывать перекомпоновку корня. Также я могу использовать DerivedStateOf и пропустить рекомпозицию некоторых дочерних элементов. Что лучше: иметь несколько потоков, которые независимо собирают и читают состояние, или иметь один поток, который вызывает перекомпозицию корня при каждом обновлении?
В первом случае UiState будет более читабельным. Во втором случае
вам понадобится одно состояние для каждого значения (например: электронная почта, пароль,
загрузка, ошибка и т. д.). Проблема в том, что в вашей ViewModel и Composables будет много
состояний.
Подводя итог, первый вариант обеспечивает улучшенную читаемость, но приводит
к большее количество рекомпозиций. С другой стороны, второй
вариант лучше подходит для обработки рекомпозиций.

Как упоминалось в комментарии @Mehdi.ncb, я Я пытаюсь найти официальную рекомендацию Google и анализ производительности, чтобы решить, какую из них реализовать. 1) UiState уровня большого экрана (https://developer.android.com/jetpack/c ... n-ui-state) который генерирует класс данных с более чем 50 полями, который перекомпоновывает весь экран. Или 2) отдельные плавные поля с меньшим количеством перекомпоновок.

Подробнее здесь: https://stackoverflow.com/questions/765 ... ck-compose
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»