Site icon AppTractor

Remote Compose: назад в будущее

«Дороги? Куда мы едем, дороги не нужны».

И, судя по всему, там, куда мы идем, нам не нужны обновления приложений для изменения пользовательского интерфейса. Давайте вернемся в будущее и посмотрим, что может предложить Remote Compose.

Что такое Remote Compose?

AndroidX незаметно представил нечто интересное. Remote Compose — это фреймворк, который позволяет определять пользовательский интерфейс на сервере и отображать его нативно на Android.

Основная идея: вы создаете документ пользовательского интерфейса на одной стороне (сервер/бэкенд), а устройство Android просто воспроизводит его. Никаких WebView, никакого сопоставления JSON-схем, никаких компромиссов в отношении кроссплатформенности.

Если вы раньше работали с пользовательским интерфейсом, управляемым сервером, пользовательскими сопоставлениями JSON с View, подходом Airbnb или ужасным путем WebView, вы знаете компромиссы. JSON-схемы не могут выражать сложные анимации. WebView снижают производительность. Пользовательские DSL-ы превращаются в кошмар при поддержке.

Remote Compose использует другой подход. Вместо описания того, что нужно отрисовать, он захватывает фактические операции отрисовки. В результате получается компактный бинарный документ, который можно передавать и воспроизводить нативно.

Представьте, что вы отправляете DeLorean во времени, только вместо человека вы отправляете целый пользовательский интерфейс.

Конденсатор потока

Итак, как же работает эта машина времени? Архитектура делится на две части.

Создание — сервер, ваш «1985». Вы пишете код, похожий на Compose, на обычной JVM. RemoteComposeWriter захватывает всё: столбцы, строки, текст, модификаторы, обработчики кликов — в бинарный формат (.rc-файл).

Воспроизведение — приложение для Android, ваше «будущее». Приложение загружает байты и передает их RemoteComposePlayer. Вот и всё. Плеер отображает всё нативно.

Клиенту не нужно знать, что такое «кнопка». Он просто выполняет операции отрисовки.

Создание документа

Давайте создадим простую кнопку. Она работает на обычной JVM, Android SDK не требуется. Вам понадобятся remote-creation-core и remote-creation-jvm.

/**
 * Remote Compose — Creating a Button Document (JVM, no Android needed)
 *
 * Produces a binary .rc document that RemoteComposePlayer can render.
 */
fun createButtonDocument(): ByteArray {
    val density = 2.625f
    fun dp(v: Int) = v * density

    val writer = RemoteComposeWriter(
        JvmRcPlatformServices(),
        RemoteComposeWriter.HTag(Header.DOC_WIDTH, (400 * density).toInt()),
        RemoteComposeWriter.HTag(Header.DOC_HEIGHT, (800 * density).toInt()),
    )

    val radius = dp(24)
    val shape = RoundedRectShape(radius, radius, radius, radius)

    val buttonMod = RecordingModifier()
        .fillMaxWidth()
        .clip(shape)
        .background(0xFF6200EA.toInt())
        .onClick(HostAction(1001, writer.addText("my_action")))
        .padding(dp(32), dp(14), dp(32), dp(14))

    writer.root {
        writer.column(RecordingModifier().fillMaxSize().padding(dp(24)), ColumnLayout.CENTER, ColumnLayout.CENTER) {
            writer.startBox(buttonMod, BoxLayout.CENTER, BoxLayout.CENTER)
            writer.textComponent(RecordingModifier(), writer.addText("Click Me"), 0xFFFFFFFF.toInt(), dp(16), 0, 600f, null, CoreText.TEXT_ALIGN_CENTER, 0, Int.MAX_VALUE) {}
            writer.endBox()
        }
    }

    return writer.encodeToByteArray()
}

Метод writer.encodeToByteArray() возвращает вам массив байтов (ByteArray), содержащий весь пользовательский интерфейс, готовый к передаче.

Воспроизведение на Android

В Android-версии всё удивительно просто. В официальной документации пока нет полного примера отрисовки (это альфа-версия), но вот всё, что вам нужно.

/**
 * Remote Compose — Rendering a document on Android
 *
 * Wrap RemoteComposePlayer in AndroidView to use in Compose.
 * Just pass binary bytes — the player handles everything.
 */
@SuppressLint("RestrictedApiAndroidX")
@Composable
fun RemoteDocumentView(
    documentBytes: ByteArray,
    modifier: Modifier = Modifier,
    onAction: (id: Int, metadata: String?) -> Unit = { _, _ -> },
) {
    key(documentBytes.contentHashCode()) {
        AndroidView(
            factory = { ctx ->
                RemoteComposePlayer(ctx).apply {
                    setDocument(documentBytes)
                    addIdActionListener { id, metadata ->
                        onAction(id, metadata)
                    }
                }
            },
            modifier = modifier
        )
    }
}

Загрузка байтов, вызов setDocument(), обработка кликов. Плеер сам отвечает за компоновку, отрисовку, обработку касаний, прокрутку — за всё.

88 миль в час

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

Поэтому я создал веб-редактор.

Конвейер:

  1. Перетаскивание элементов пользовательского интерфейса в браузере
  2. Нажатие кнопки «Развернуть», отправка макета в формате JSON на GitHub
  3. GitHub Action преобразует JSON в бинарный документ .rc с помощью RemoteComposeWriter
  4. Приложение для Android загружает документ .rc и отображает его

Предварительный просмотр в веб-редакторе осуществляется с помощью Compose for Web (Kotlin/Wasm), поэтому то, что вы видите в браузере, максимально соответствует устройству.

Весь процесс создания выполняется на стороне сервера. Android SDK не используется.

На момент написания статьи Remote Compose находится в версии 1.0.0-alpha05. Это ранняя версия. API будут меняться. Но основа прочная. И с приближением Google I/O я не удивлюсь, если Remote Compose получит больше внимания.

На этом всё на сегодня

Remote Compose предлагает новый подход к разработке пользовательского интерфейса Android. У меня есть ещё много идей для дальнейшего развития, следите за обновлениями и поставьте лайк, если вам понравилась статья.

Вы можете найти меня в X — https://x.com/ArmanChatikyan
LinkedIn — https://www.linkedin.com/in/chatikyan

Спасибо за прочтение этой статьи. Надеюсь, вам понравилось.

Ресурсы

Источник

Exit mobile version