Привет, энтузиасты Kotlin и Jetpack Compose!
Мне не терпится поделиться библиотекой, которая может изменить ваши представления о том, как вы используете превью Jetpack Compose.
Если вы когда-либо тратили драгоценное время на создание фиктивных классов с многочисленными параметрами для сложных предварительных просмотров Compose или реализовывали мобильную функциональность без готового бэкенда, эта библиотека может стать вашим помощником номер один.
Представляем вам Preview Generator, созданный с помощью KSP (Kotlin Symbol Processing) и доступный в репозитории Sonatype, ранее известном как Maven Central. И это полностью открытый исходный код! 🚀
Демо
Вот небольшой повседневный пример того, как PrevGen может значительно упростить разработку представлений Compose. Представьте, что вам нужно отобразить историю транзакций, показывая такие детали, как отправитель (fromUser), получатель (toUser), данные обоих пользователей, сумму, статус, дату и многое другое. Ниже приведена модель данных и Compose CardView, которую мы хотим просмотреть:
Модель данных:
data class PaymentHistoryItem( val _id: String, val amount: Int, val currentBalance: Int, val date: Long, val fromUser: User, val id: String, val oldBalance: Int, val toUser: User, val status: String )
И Compose CardView:
@Composable fun HistoryCard(paymentHistoryItem: PaymentHistoryItem, onClick: () -> Unit) { Card(modifier = Modifier.padding(vertical = 4.dp, horizontal = 4.dp).clickable(onClick = onClick)) { Column(Modifier.padding(8.dp)) { Row(Modifier.fillMaxWidth().padding(2.dp), Arrangement.SpaceBetween) { Text(text = "From: ${paymentHistoryItem.fromUser.name}") Text(text = "Status: ${paymentHistoryItem.status}") } Row(Modifier.fillMaxWidth().padding(4.dp), Arrangement.SpaceBetween) { Text(text = "to: ${paymentHistoryItem.toUser.name}") Text(text = "Amount: ${paymentHistoryItem.amount}") } Divider(thickness = 1.dp, color = Color.Gray) Row(Modifier.fillMaxWidth().padding(2.dp), Arrangement.SpaceBetween) { Text(text = "Date: ${paymentHistoryItem.dateString}") Text(text = "Balance: ${paymentHistoryItem.currentBalance}") } } } }
Обычно вы создаете фиктивные классы данных и вручную заполняете их экземпляры для предварительного просмотра, как показано в фабричной функции предварительного просмотра:
fun createTestData() : PaymentHistoryItem { val fromUserA = User( _id = "user123", fullName = "John Doe", hasProducts = true, id = "user123", location = Location(lat = 40, long = -74), name = "John", surname = "Doe", username = "johndoe" ) val toUserB = User( _id = "user456", fullName = "Jane Smith", hasProducts = false, id = "user456", location = Location(lat = 34, long = -118), name = "Jane", surname = "Smith", username = "janesmith" ) return PaymentHistoryItem( _id = "abc123", amount = 100, currentBalance = 500, date = System.currentTimeMillis(), fromUser = fromUserA, id = "def456", oldBalance = 400, toUser = toUserB, status = "credit" ) }
А для предварительного просмотра добавьте функцию с аннотацией preview
и используйте ее здесь, например:
@Preview @Composable fun HistoryCardPreview() { HistoryCard(paymentHistoryItem = createTestData()) {} }
Также обратите внимание, что в случае изменений в структуре, вам нужно будет обновить эти фиктивные экземпляры в createTestData()
. 😞
С PrevGen этот процесс становится простым. Для этого примера мы просто добавим @DataPreview
в наш класс верхнего уровня:
@DataPreview data class PaymentHistoryItem(...)
После перекомпиляции проекта вы сможете легко использовать его в своей функции Compose:
@Preview @Composable fun HistoryCardPreviewWithPrevGen() { HistoryCard(paymentHistoryItem = paymentHistoryItemPreview) {} }
Вот сравнение между созданием тестовых экземпляров вручную и их автоматической генерацией с помощью PrevGen:
Все выглядит примерно одинаково, верно? Если да, то зачем тратить время на создание и обновление данных в превью? Кроме того, не нужно добавлять в кодовую базу шаблонный код.😎
Больше не нужно вручную искать и обновлять фиктивные данные. PrevGen упрощает Compose-разработку, позволяя вам сосредоточиться на создании потрясающих пользовательских интерфейсов!
Настройка
Вот как все это настроить. Как я уже говорил, это генератор кода, созданный с помощью KSP.
1. Добавьте плагин KSP в основной файл build.gradle:
plugins { // ... id("com.google.devtools.ksp") version "1.9.21-1.0.15" // get needed version }
2. Добавьте MavenCentral в репозитории:
repositories { // ... mavenCentral() }
3. Добавьте KSP и модуль в зависимости Gradle:
dependencies { // ... // For the latest version, check the GitHub repository. implementation("io.github.vram-voskanyan.kmp:PreviewGenerator:1.0.0") ksp("io.github.vram-voskanyan.kmp:PreviewGenerator:1.0.0") }
4. Синхронизируйте проект, и все готово. Аннотация @DataPreview
будет доступна.
Чтобы получить последнюю версию или обновления, следите за репозиторием GitHub.
Планы
Вот краткое изложение того, что у нас есть и что мы в настоящее время не поддерживаем:
- Поддерживаемые типы: классы данных, примитивные типы String, Int, Long, Boolean.
- Логика генерации значений для имен аргументов, таких как возраст, дата, имя, адрес и т.д.
- Многоплатформенная поддержка Kotlin: в настоящее время, если вы посмотрите на MavenCentral, пакет JVM также собран и включен в путь, но он не протестирован. Не стесняйтесь попробовать и обращаться ко мне по любым вопросам или за помощью.
Проблемы:
- Проблема с рекурсией (например, класс данных A(list: List<A>()) — это будет бесконечный цикл. Он будет бесконечно пытаться создать экземпляр «A».
- Перечисления не поддерживаются: вместо этого используйте nullable.
Заключение
Если вы зашли так далеко, значит, вы нашли что-то интересное. Спасибо за внимание!🎉
Продолжайте следить за контентом. Думаю, следующая тема будет связана с мультиплатформой, потому что мы верим, что за ней будущее.