Kotlin Adept Notes
1.98K subscribers
67 photos
10 videos
114 links
Канал о разработке на Kotlin и обо всем, что с ним связано
По всем вопросам и рекламе: @ajiekcx
Download Telegram
Рубрика идиоматичный Kotlin. Что вернет выражение listOf(false).any() ?
Anonymous Quiz
54%
true
46%
false
🤝17😁1🤯1
This media is not supported in your browser
VIEW IN TELEGRAM
Адаптивный UI проще, чем кажется

Раньше с Android View, если требовалось поддержать верстку для планшетов, довольно часто просто делали отдельную верстку с нуля, и несмотря на то, что можно было расположить несколько фрагментов на одном экране, это не избавляло от сложностей навигации 🥲

Теперь же с приходом Compose и нового api делать адаптивную верстку стало значительно проще. И вот несколько рекомендаций как сделать современный адаптивный UI:

1️⃣ Не используйте флаги вроде isTablet и т.д., используйте window size classes для динамического определения размера окна: Compact, Medium, Expanded

2️⃣ Используйте готовые адаптивные компоненты вроде ListDetailPaneScaffold, SupportingPaneScaffold, NavigationSuiteScaffold

3️⃣ Рассмотрите возможность использования LazyGrid вместо LazyList

4️⃣ Меняйте расположение UI компонентов с помощью BoxWithConstraint и movableContentOf во избежание лишних рекомпозиций

5️⃣ Не блокируйте ориентацию экрана и не отключайте resizeableActivity

6️⃣ Меняйте размер и соотношение сторон у UI компонентов в зависимости от размеров окна

🌳 В Decompose также появилась поддержка адаптивной навигации и благодаря ChildPanels реализовать list-detail навигацию стало очень просто без лишнего бойлерплейта.

А есть ли адаптивная верстка в вашем приложении
🫡 — только screenOrientation portrait, только хардкор
😎 — есть адаптивная верстка под любые экраны

#Compose #AdaptiveUI
@kotlin_adept
Please open Telegram to view this post
VIEW IN TELEGRAM
🫡55😎6👍5❤‍🔥21
Целую неделю при работе с Compose Multiplatform для JS ловил какие-то фантомные баги, связанные с тем, что отваливался Applier, то все работало, то падало в рантайме 🤩

Applier — это платформенная сущность, которая на основе списка изменений создает дерево узлов на дальнейшую отрисовку.


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

Здесь есть те, кто гадает по мемам? Пишите свои предположения, в чем была проблема, в комментарии 👇
Please open Telegram to view this post
VIEW IN TELEGRAM
😁18😱5
🔔 Напомню, что сегодня в 19:00 мск пройдет стрим, где будут два интересных доклада. Подробнее здесь.

🤖🍏 Доклады будут полезны как Android, так и iOS разработчикам.

Так что приходите посмотреть доклады, пообщаться в чате с другими участниками, задать вопросы спикерам, ну и просто с пользой провести время 😉
19👍4
Live stream started
Live stream finished (1 hour)
Мы в команде недавно подняли свой сервис автоматизации на Kotlin и реализовали там много всяких полезных штук:

🟣 Интеграция YouTrack и GitLab для автоматического перевода тасок в актуальное состояние и заполнения данных
🟣 Напоминание о забытых ревью
🟣 Уведомления о релизах
🟣 И другие полезные мелочи

🔖 Подробнее о наших процессах и как мы делали такой сервер читайте в статье.

〰️ И пишите в комментарии какие must have автоматизации есть в ваших процессах

#Kotlin #Ktor #Server
@kotlin_adept
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍4👏1😎1
Как установить iOS приложение из браузера

Недавно пришлось на практике столкнуться с этой задачей и мой необремененный мозг Android разработчика ожидал, что все будет очень просто 😆

Вот у нас есть установочный .ipa файл и мы просто загружаем его в браузере и система любезно предлагает установить его по аналогии как это работает с .apk файлами на Android думал я...


Но Apple не была бы Apple, если бы не придумала как сделать разработчикам максимально больно, поэтому здесь не все так просто и вот как это выглядит на самом деле:

🟡 Разумеется наш установочный ipa файл должен быть подписан подписью разработчика и UUID тестовых устройств должны быть прописаны в админке Apple, но сегодня не об этом.

🟡 Далее формируем ссылку для установки приложения в следующем виде:

itms-services://?action=download-manifest&url=your_url

И если вы подумали, что здесь должна быть ссылка на ipa файл, то придется вас огорчить. Здесь должна быть ссылка на специальный манифест в виде plist файла, где указано имя приложения, его версия и наконец ссылка на скачивание файла.

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

Так что простая, на первый взгляд, задача превратилась в приключение совсем не на 20 минут.

💭 А как вы распространяете дебажные сборки iOS приложений?

#iOS
@kotlin_adept
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯9👍2🔥2
Написал небольшую статью о рефакторинге архитектуры приложения с запутанной логикой.

По итогу получилось значительно  упростить логику приложения и повысить надёжность. В этом помогли корутины, а точнее их не совсем стандартное применение.

Приятного чтения 📖

#Architecture #Coroutines
@kotlin_adept
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29🔥5
SwiftExport

Вчера вышел Kotlin 2.1, и мы стали еще на один шаг ближе к тому, чтобы отказаться от прослойки с Objective-C хедерами и использовать скомпилированный Kotlin-код напрямую в Swift 😎

Но интересно даже не это — теперь, наконец, станет возможным разделять код на разные модули для Swift. Раньше все фичи, использующие KMP, могли обращаться к любой его части, а теперь это можно инкапсулировать.

🐱 Посмотреть пример кода можно здесь.

P.S. Я же очень жду возможность использования нескольких KMP библиотек в одном Swift проекте без создания umbrella модуля, чтобы была возможность переиспользовать рантайм Kotlin Native и общие библиотеки.

#KMP #Swift
@kotlin_adept
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥9
Тем временем я вернулся на проект с KMP для JS, и вот так выглядит загрузка файлов...
❤‍🔥14🙈7👍1
Как подключить KMP в iOS проект без CocoaPods

Я задумался об этом еще в прошлом году и подключил всё, как описано в инструкции. Но как только в Xcode-проекте появились кастомные конфигурации, начало происходить нечто странное...

Проект продолжал компилироваться, но при этом все новые изменения в общем коде перестали отображаться в Xcode. А если почистить кеш, то и вовсе выводилась ошибка: "No such module Shared". Я поспрашивал в чате, сталкивался ли кто-то с подобной проблемой, но узнал лишь, что с CocoaPods всё работает хорошо. Поэтому я просто забил и перешел на CocoaPods, думая, что, если проблема есть, её наверняка исправят 🔥

Однако CocoaPods стали deprecated, и вся наша iOS-команда уже давно мигрировала на SPM. Представьте лица iOS-разработчиков, к которым вы не только притащили KMP, но еще и хотите заставить их вернуться на CocoaPods 👍

Поэтому я снова вернулся к этой задаче и, к моему удивлению, спустя год ничего не изменилось: проблема всё ещё присутствует даже на новых версиях. Я стал разбираться и выяснил, что по каким-то причинам Xcode визуально подтягивает только фреймворк по пути build/xcode-frameworks/debug. Но путь для сборки фреймворка меняется, как только появляются кастомные конфигурации, и отвечает за это переменная окружения CONFIGURATION.

Тут я подумал: а зачем нам вообще разделять на разные папки для каждой конфигурации? В любом случае каждую конфигурацию мы маппим в Debug или Release build type с помощью переменной KOTLIN_FRAMEWORK_BUILD_TYPE.

Поэтому я для себя сделал следующий workaround. В Build Phase в Xcode, где собирается Kotlin-фреймворк, нужно переопределить переменную окружения конфигурации:


export CONFIGURATION=$KOTLIN_FRAMEWORK_BUILD_TYPE
cd "$SRCROOT/.."
./gradlew :shared:embedAndSignAppleFrameworkForXcode


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

Официального ответа по этому issue я всё ещё не получил, поэтому поддержите лайком, чтобы команда JetBrains заметила и дала официальные рекомендации.

#KMP #Xcode #iOS
@kotlin_adept
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥22👏54👍1
5 причин порешать AdventOfCode

В этом году решил порешать рождественские задачки на любимом Kotlin, и это на самом деле интереснее и полезнее, чем кажется на первый взгляд. Особенно учитывая, что мне абсолютно никак не откликается LeetCode и нет никакого желания решать алгоритмические задачки, если я не собираюсь идти на собеседование.

Поэтому вот 5 причин, почему вам тоже стоит хотя бы раз попробовать AoC:

1. Вы решаете непривычные для себя задачи, тем самым развивая нестандартное мышление.
2. Даже если вы решаете на своем привычном языке, далеко не факт, что вы используете все его возможности. Вы сильно удивитесь, как одну и ту же задачу можно было решить намного элегантнее, посмотрев решения других участников.
3. Можно поорать с мемов на том же реддите. Решать задачи одновременно с коммьюнити гораздо интереснее!
4. Вы открываете для себя новые языки. Например, UIUA: на первый взгляд, синтаксис этого языка выглядит как ошибка кодировки символов, но задачи на нем решаются в пару строчек, тогда как на Kotlin придется написать в десятки раз больше кода.
5. Ну и просто заряжаетесь новогодним настроением, ведь у всех задач есть какой-никакой общий рождественский сюжет 🔥

Ставьте 🎅, если тоже участвуете в AdventOfCode!

#AdventOfCode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🎅13🤔21🎄1
Внезапно появилось желание адаптировать какой-нибудь KMP-проект под Аврору, и я решил узнать, как это сейчас можно сделать малой кровью. Почитал статью, посмотрел доклад, и в итоге на сегодняшний день ситуация выглядит следующим образом.

Если не брать во внимание экзотику вроде GraalVM и Kotlin Native, где нужного таргета нет почти ни в одной библиотеке, то остается только интероп через Kotlin JS и QML.

Почему-то я нигде не нашел примера с Compose для JS на Авроре. Возможно, на это есть причина, но, кажется, это наш выбор, так как почти все ключевые библиотеки поддерживают JS-таргет.

Идея очень проста: отображаем весь UI в WebView и вызываем платформенный API через колбэки с JavaScriptInterface.

За производительность, кажется, можно не переживать. По опыту, Compose в браузере работает даже быстрее, чем на iOS. Главная проблема Compose для JS — это большой бандл, но это не критично, если бандл поставляется вместе с приложением 🧠

Главным камнем преткновения может стать то, что сейчас WebView в Авроре использует движок Gecko, однако в обозримом будущем планируется миграция на Chromium, и тогда все должно быть в порядке.

Очень хочется проверить эту теорию и запустить хотя бы сэмпл. Но нужного SDK под Apple-процессоры до сих пор нет в публичном доступе, так что пока ждем ⌚️

#Aurora #KMP
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥22💊11👎2😁2👏1
#видеозаписи

Когда начинаешь публиковать записи докладов Mobius, с какой платформы логичнее приступать, Android или iOS?

С обеих сразу: в этот #МобильныйВторник открываем доклад, где речь про обе.

YouTube | VK Видео

Скачать презентацию с сайта Mobius
👍191
Compose Multiplatform в проде

Хочу поделиться новостью: мы выпустили первое приложение, полностью написанное на Compose Multiplatform для iOS 😌

Изначально приложение разрабатывалось только для Android, но использовался Kotlin-стек (Decompose, Ktor, SqlDelight, Koin) и обычный Jetpack Compose. Чтобы запустить его в каком-то виде на iOS, потребовалось всего 4 дня! Конечно, доведение до релиза заняло значительно больше времени, но всё равно это оказалось гораздо быстрее, чем полноценная разработка аналогичного проекта с нуля.

Что по итогам:
🟣Compose в релизной версии вполне прилично работает, особенно на новых устройствах с поддержкой 120 Гц
🟣Управление жестами удалось легко реализовать благодаря Decompose
🟣Скролл подлагивает и не ощущается как нативный
🟣BottomSheet, как всегда причиняет боль 😬
🟣Есть некоторые баги с TextField
🟣Некоторые контролы пришлось реализовать нативно, например, WebView, TimePicker и т.д.

Тем не менее, я уверен, что многие проблемы будут исправлены в будущем и уже сейчас Compose Multiplatform можно использовать в проектах, где плавность интерфейса не является критически важной 👍

#iOS #Compose
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥55👍5👏2🤔21
Как подружить Web History и Compose resources

Недавно столкнулся с проблемой: после добавления поддержки Web History в проект с Compose для Web у меня перестали работать ресурсы, причём это происходило только на вложенных экранах.

Изначально я предположил, что проблема связана с настройками веб-сервера, но нет. В Compose для Web ресурсы загружаются по относительному пути. Это означает, что к текущему URL в браузере добавляется путь до ресурсов. Соответственно, если вы находитесь не на главной странице, то по такому пути ресурсы окажутся недоступными 🫥

Посмотрел, что пишут в документации, но никаких рекомендаций там не дается на этот счет, что довольно странно. Поправить же проблему удалось следующим образом:


configureWebResources {
resourcePathMapping { path -> "${location.origin}/$path" }
}


Добавляем этот код в функцию main в сорсете jsMain, и пути до ресурсов снова становятся корректными.

#Compose #JS #WEB
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22😨4
Интероп suspend и async функций

Ранее все suspend-функции в Kotlin превращались в обычные функции с completionHandler на стороне Swift, но начиная с Swift 5.5 появился интероп между корутинами в обе стороны. Однако пусть это не вводит вас в заблуждение: это всего лишь "сахар" в Swift, который преобразует коллбэки в асинхронные функции ❗️

Соответственно, у вас будет работать базовый сценарий использования асинхронной функции, но на этом из хороших новостей всё:
Запуск async-функции на Main-диспетчере не гарантирует выполнения на главном потоке в Swift.
CancellationException не будет преобразовываться в CancellationError, соответственно, не будет работать кооперативная отмена корутин и есть риск получить work leak.

💡 Казалось бы, с этой проблемой может помочь библиотека SKIE, но и там не всё гладко. Она исправляет только интероп в одну сторону, когда мы вызываем suspend-функции из Swift-кода, но не в обратную.

Так что будьте осторожны с таким интеропом и следите за развитием полноценной поддержки в соответствующем issue.

#Coroutines #Kotlin #Swift
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15😁1