Search
Write a publication
Pull to refresh

Comments 10

Выглядит красиво. Ещё бы поставить вместе картинки было-стало, иначе тяжело в статье улавливать нюансы.

Спасибо за отзыв!

Можешь уточнить, где именно не хватило картинок было-стало? Старался оформлять именно с той целью, чтобы было несложно сравнивать варианты и сохранить структуру:)

Возможно стоило где-то в статье поставить 2 окна в ряд с карточками, что было и что стало, и уже потом под ними подробнее описывать изменения. Сейчас окна "было" находится выше, окно "стало" ниже, поэтому образ старой карточки "вызывается" из памяти), что не так наглядно.

Нет, семпл апп мы не публиковали. Он у нас есть, но для внутреннего использования

Спасибо за статью!

Как же задолбало, что дизайнеры натягивают дизайн iOS на Android. Системы разные с точки зрения UX, и хочется пользоваться Android-опытом, а не iOS на устройствах Android ?

Да, есть такая боль. Но дизайн чаще один рисуется, так что это всегда перекос в чью либо сторону. Если и есть разделение, то в виде контролов навигации и мелких штук. Что конечно расстраивает

С другой стороны, мы получаем одинаковый опыт пользования продуктовым решением. Если фича выглядит и там, и там одинаково, то опыт будет плюс-минус таким же. Даже если пользователи поменяются телефонами, то они не потеряются)

Подскажите пожалуйста, как лучше организовать код:

1) Скинуть всё для одного экрана в один .kt файл или разбить на разные файлы по элементам?

  • с одной стороны хорошо иметь всё в одном файле, но если экран большой и сложный, то будет огромное число строк и превью дольше рисуются.

  • с другой стороны, когда кидаешь компоненты в другие файлы, они становятся публичными функциями и тогда при рисовке другого экрана будут показыватся при поиске компонентов по имени. Например мне нужна кнопка, и я пишу Button, тогда мне покажутся и, предположим, ButtonSpecialForScreen1... Screen2, соответственно. Чего хотелось бы избежать, но сейчас работаю именно в таком ключе.

2) Где хранить стейт для функции, в том же документе что и сама Composable функция или рядом в package models/states или где-то ещё?

  • Есть ещё вариант создания вложенного стейта, когда в один стейт экрана вкладывать другие стейты, из которых он состоит

  • Другой путь, писать отдельные стейты для функций а потом просто создать матрёшку из нужных стейтов.

1. Мы в команде придерживаемся подхода, когда каждый элемент размещен в отдельном kt файле. При этом мы не разделяем элементы, которые тесно связаны друг с другом и будут использоваться только в контексте виджета. Это решит проблему видимости элементов-компонентов, которые нужно использовать только локально, просто делаем private
Верхнеуровневые будут оставаться, с этим придется жить, но и тут если проект многомодульный, то ставить internal у внутрянки, остальное public

2. Стейт мы храним в отдельном файле. Даже если это простой data class с одним полем, все равно так проще и легче их искать в дереве. Кладем их в том же package, где и объявляется Composable функция.

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

Допустим с этой карточкой продукта у нас есть большой комплексный стейт всего экрана, который состоит из стейтов разных его частей. И по сути это совмещает оба твоих поинта. У нас отдельные Composable методы требуют свой узкий стейт, но при этом все они собираются в один большой.

@Immutable
data class NutritionState(
  val calories: NutritionElement = Calories(),
  val weight: NutritionElement? = Weight(),
  val protein: NutritionElement = Protein(),
  val fat: NutritionElement = Fat(),
  val carbs: NutritionElement = Carbs(),
  val isCompositionButtonVisible: Boolean = true,
)

Когда отдельно взятый, например, NutritionState выглядит так:

@Immutable
data class ProductState(
  val compositeProductName: String = "",
  val titleTheme: TitleTheme = DEFAULT,
  val isLoading: Boolean = false,
  val videoUrl: String? = null,
  val imageUrl: String? = null,
  val previewUrl: String? = null,
  val customizeState: CustomizeState = CustomizeState(),
  val description: DescriptionState = DescriptionState(),
  val composition: CompositionState = CompositionState(),
  val nutrition: NutritionState? = null,
  val price: PriceButtonState = PriceButtonState(),
) : MVIState

И есть виджет Nutrition – в нем отображается пищевая ценность, будет требовать этот стейт Composable методе

Кстати нам показалось неудобным использовать sealed классы для разных стейтов экрана, потому что терялись данные при таком подходе, которые уже были в стейте. Подход с добавлением отдельного поля isError и isLoading в стейт оказалось проще для обработки внештатных ситуаций в интерфейсе

Sign up to leave a comment.