Compose Multiplatform: общий UI

Когда хочется делить и интерфейс: Compose Multiplatform рисует общий UI на нескольких платформах.

Compose Multiplatform — фреймворк от JetBrains, переносящий декларативный UI Jetpack Compose на iOS, desktop и web, позволяя делить не только логику, но и интерфейс.

Смена компромисса

До сих пор мы делили логику, а UI оставляли нативным. Compose Multiplatform предлагает другой компромисс: делить и UI тоже, написав его один раз на Compose. Это сближает KMP с Flutter — общий интерфейс на собственном движке отрисовки. Под капотом Compose рисует на Skia, как и Flutter, поэтому UI выглядит одинаково на всех платформах (а не как нативный по умолчанию).

Где работает

ПлатформаСтатус
Androidстабильно (это и есть Jetpack Compose)
Desktop (JVM)стабильно
iOSстабильно в современных версиях
Web (Wasm)развивается, ближе к проду в свежих релизах

Один Composable на всех

// commonMain (с Compose Multiplatform)
@Composable
fun OrderListScreen(viewModel: OrderListViewModel) {
    val state by viewModel.state.collectAsState()
    Column {
        when (state) {
            is OrderListState.Loading -> CircularProgressIndicator()
            is OrderListState.Data -> LazyColumn { /* элементы */ }
            OrderListState.Error -> Text("Ошибка")
        }
    }
}

Этот экран компилируется и под Android, и под iOS, и под desktop. UI стал частью общего кода.

Как работает под капотом

На Android Compose Multiplatform — это и есть Jetpack Compose. На iOS и desktop JetBrains реализовали свой рендерер поверх Skia, который рисует те же Composable-функции. То есть Composable-дерево одно, а «доска для рисования» — платформенная. Интеграция с нативным экраном идёт через хост-вью: на iOS Compose-контент кладут в UIViewController, на desktop — в окно. Это позволяет встраивать общий Compose-UI в нативное приложение постранично.

Нативный UI против Compose MP: как выбрать

Берите нативный UI, когда критичен идеальный платформенный look-and-feel и доступ к самым свежим системным виджетам. Берите Compose Multiplatform, когда важнее скорость разработки и единый UI, а небольшие отличия от нативного приемлемы. Часто их комбинируют: общий Compose для большинства экранов, нативные вставки там, где нужно.

Частые ошибки

Считать, что Compose MP отрисует «нативные» компоненты iOS — нет, он рисует свои (Material по умолчанию), как Flutter. Если нужен точный iOS-вид, это дополнительная работа. Вторая ошибка — ждать от веб-цели той же зрелости, что у Android; web на Wasm моложе. Третья — забыть, что общий ViewModel и общий Compose — разные уровни: можно делить только логику, а UI оставить нативным.

Итоги

  • Compose Multiplatform делит и UI, рисуя его на Skia, как Flutter.
  • Android/desktop/iOS — зрелые цели; web на Wasm моложе.
  • Один Composable работает на всех платформах.
  • Выбор между нативным UI и Compose MP — это выбор компромисса look-and-feel против скорости.
Проверьте себя
1. Чем Compose Multiplatform похож на Flutter?
AИспользует JavaScript
BРисует общий UI собственным движком (Skia), а не нативными компонентами
CНе поддерживает iOS
DРаботает только в вебе
2. Какая цель Compose Multiplatform наименее зрелая?
AAndroid
BDesktop
CiOS
DWeb (Wasm)