Ra'Reilly - Заметки про Ktor и не только – Telegram
Ra'Reilly - Заметки про Ktor и не только
975 subscribers
71 photos
133 links
Каждую неделю (нет) тут появляются заметки.
В основном про около-Ktor, но иногда и про тулинг залетает.

Автор: @osipxd
Download Telegram
Выпустил обновление 2.0-rc1 для mapmemory.
Эта библиотека позволяет быстро реализовать in-memory кэш.

Полностью release notes пересказывать не буду, но вот что хочется отметить:
- Теперь значения в MapMemory могут быть scoped и shared. Scoped ограничены к использованию только внутри класса где объявлены, shared можно шарить межу классами.
- Новый модуль mapmemory-test с утилитами для удобного тестирования классов, использующих MapMemory.
- Добавил поддержку RxJava 3
- Переписал README и KDoc комментарии. Жду комментов всё ли понятно теперь :)
- Упростил синтаксис для объявления nullable полей и полей со значением по умолчанию.

Гайд по миграции с v1.1 добавил в README.

#library
Пошёл на выходных обновить mapmemory, но споткнулся о баг в котлине и не дошёл.

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

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

#bug #kotlin
Если вы с одного устройства коммитите и в рабочий git-репозиторий, и в личный, наверняка были случаи, когда закоммитили код не с той почтой и именем.
И вот запушил что-то в рабочий проект с личного аккаунта, а потом сидишь и вычищаешь это через rebase перфекционизму ради.

Простой способ этого избежать — после того как стянул себе проект настроить всё что надо через git config. Если проектов много, а нужно настроить не только имя и email, но и ключ для подписи, например, это не удобно.

Более универсальный способ — использовать в глобальном .gitconfig настройку includeIf. Как можно понять из названия, эта настройка применит конфиги из другого файла, если выполняется условие. Синтаксис для определения условий достаточно ограниченный, но можно проверить в какой папке находится проект и в зависимости от этого применить настройки. У себя использую эту штуку так:

[includeIf "gitdir:~/dev/rmr/"]
path = .gitconfig.rmr

В этом случае настройки из общего .gitconfig применяются ко всем проектам, а для проектов из папки dev/rmr/ некоторые настройки переопределяются в файле .gitconfig.rmr

#git
Можете считать, что меня только что разморозили, но я только вчера узнал про git subtree.
Это альтернатива git submodule. Как и submodule, subtree позволяет подтянуть другой репозиторий внутрь вашего, но отличается подход.

submodule оставляет "метку", что "в этой папке должна лежать такая-то ревизия такого-то репозитория". Физически файлов из другого репозитория в вашем репозитории нет и чтобы они появились, нужно выполнить определённую команду. Наверное, это больше всего отпугивает от submodule — чтобы получить полностью рабочий репозиторий, недостаточно его клонировать, нужно ещё выполнить дополнительные действия.

subtree физически добавляет файлы из другого репозитория в ваш репозиторий вместе с историей коммитов. Процесс клонирования репозитория никак не меняется и другие разработчики могут не знать, что в проекте есть subtree. Файлы из "поддерева" можно изменять так же как с остальные файлы проекта

Про submodule должны знать все разработчики, а знать о subtree нужно только в момент когда хочется стянуть изменения из удалённого репозитория (pull) или наоборот запушить туда свои (push).

# Добавляем удалённый репоизторий для subtree
$ git remote add --fetch <repo_name> <url>

# Стягиваем его в нужную папку
$ git subtree add --prefix <dir> <repo_name> <ref>

# Ну и дальше можем делать fetch, pull, push
$ git subtree fetch --prefix <dir> <repo_name> <ref>
$ git subtree pull --prefix <dir> <repo_name> <ref>
$ git subtree push --prefix <dir> <repo_name> <ref>

P.S. Осталось научиться нормально синхронизировать файлы выборочно между репозиториями и будет совсем хорошо. Буду конфиги шарить направо и налево.

#git
Сегодня убил кучу времени на баг которого не существует.

В апишке есть метод, который возвращает 204 No Content. Тестировщик подменил код ответа на 500, чтобы проверить как приложение реагирует на ошибку и в результате получилось такое поведение:
→ Запрос улетает
← Приходит ответ с кодом 500 (видно по логам)
... Приложение чего-то ждёт и запрос отваливается по таймауту.
Что? Да. Запрос, ответ на который уже вроде как пришёл отваливается по таймауту.

Отгадка отказалась проста. Ответ 204 не подразумевает тела и в нём нет заголовка Content-Length, а вот для 500 тело может прийти и Content-Length должен быть определён. В результате у HTTP-клиента ломается мозг и он до таймаута ждёт пока ему долетят остатки ответа, которых не существует.

Мораль — перед тем как чинить, убедитесь, что оно сломано :) А если серьёзно, то внимательнее смотрите на запросы и ответы которые тестировщики делают частичной подменой данных.
А теперь к важным новостям!
На GitHub поменяли цвет для Kotlin и теперь его не перепутать со Swift.
Московские роботы-андроиды* выкатываются на YouTube!
Дебютное видео про всеми любимый Gradle.

Первые 50 минут теория, где:
- Разбираем какие могут возникнуть проблемы с Groovy у Java/Kotlin разработчика
- Смотрим как мигрировать с Groovy DSL на Kotlin DSL
- Кратко пробегаемся по основным APIшкам Gradle которые нужно знать, чтобы перейти ко второй части доклада.

Жанр второй части я бы назвал "косячный live coding", потому что это не тот live coding когда у докладчика всё отрепетировано и нет никаких проблем, а когда вы пробуете что-то написать самостоятельно, тут же огребаете. Тут собраны все косяки которые скорее всего соберёт человек, который впервые пишет плагины под Gradle.

Вторая часть длится полтора часа и в ней:
- Пишем Precompiled Script Plugin (после того как везде исправлял это название на монтаже я выучил как правильно!)
- Пишем плагин, с возможностью конфигурирования
- Пишем задачку (task). Делаем, чтобы в неё работало кэширование и создаём цепочки из задач

И это всё на близком к реальности Android-проекте.
Кстати, это один из докладов с нашей ежегодной робопрактики мобильных разработчиков.
Как говорится, подписывайтесь, ставьте лайки, рассказывайте друзьям :) Если понравится, будем продолжать.

* Мы в red_mad_robot не обижаемся, когда нас называют роботами, а даже наоборот сами себя так называем

#анонс #tooling
Оказывается, плагин kotlin-android (и другие kotlin-плагины) по умолчанию добавляют в зависимости stdlib. Такое поведение появилось начиная с версии 1.4.

Причём работает эта штука достаточно умно — она в зависимости от вашего "окружения" выбирает что подключать: stdlib-jdk8, stdlib-common или вообще stdlib-js.
НО если вы руками объявили зависимость stdlib, она уже не будет добавляться автоматически.

Конечно, оставили флажок на случай если вы не хотите полагаться на эту логику, а хотите просто отключить автоматическое добавление stdlib. В gradle.properties нужно добавить такую строчку:

kotlin.stdlib.default.dependency=false

Ещё один интересный момент — версия для автоматически добавляемой зависимости берётся из свойства kotlin.coreLibrariesVersion. В это свойство по умолчанию записывается версия подключённого kotlin-gradle-plugin, но её можно перезаписать.
Благодаря этим строчкам версия из kotlin.coreLibrariesVersion используется для всех зависимостей org.jetbrains.kotlin.
Ещё один способ выбрать общую версию Kotlin для всего проекта.

#kotlin #gradle
Всё. Теперь не работают отговорки типа "на Android не принято заголовок по центру тулбара делать", "это системное поведение, его нельзя поменять". Теперь можно.
#ui
Через неделю - 27-го июля с утра буду выступать на Podlodka Android Crew с рассказом про Git.
Планирую рассказать много всего - про чистоту истории, атомарные коммиты, разные модели ветвления, как всё-таки заставить всех разработчиков следовать договорённостям. Еще хочу обзорно рассмотреть полезные функции - cherry-pick, patch, stash и т.д. и как это всё ложится на Android Studio (читай IntelliJ IDEA).

Думаю, что доклад будет слабо связан с Android, поэтому может быть интересен не только андроид-разработчикам. Ссылка на запись доклада появится на этом канале :)

#анонс #git
Чтобы было не скучно ждать пока мы зальём что-то ещё на канал, появился плейлист "Это тоже мы". Туда я складываю выступления с площадок вне нашего канала (пока что все, хе-хе).

Как и обещал, добавил в этот плейлист ссылку на свой доклад про Git с подлодки. Там доступ по ссылке, поэтому если вы не купили билет, то посмотреть можно пока только с нашего канала.

В общем, по классике - подписывайтесь, ставьте лайки, рассказывайте друзьям и вот это всё :)

#rmr #анонс
Просматривал исходники AGP 7.0.0 и заметил, что теперь папка kotlin по умолчанию добавлена в source-set и больше не нужно делать это вручную, если подключён Kotlin Gradle Plugin.
Вот этот коммит.
В release notes AGP этого изменения не нашел.

#kotlin #gradle
На нашем канале пока тихо, зато Саша Серебренникова (@serebrennik) записала для @android_broadcast аж сразу серию видео про Custom View! Я уже посмотрел два из трёх видео и всем советую — Саша нереально крутая. Наконец материал с нормальными примерами, а не "нарисуем зелёный треугольничек с красным квадратиком".

Ссылочку на плейлист уже добавил на канал, чтобы все наши выступления можно было найти в одном месте :)

#ui #анонс
Так-так-так. Material 3 - это что за покемон?

#ui
Довольно вкусный RC kotlinx.serialization подвезли!
- (Де)сериализация стримов - Json.encodeToStream и Json.decodeFromStream
- В конфиге появился флажок explicitNulls с помощью которого можно отключить явную сериализацию null
- Теперь можно определять дискриминатор для классов по отдельности (для полиморфных типов). Раньше можно было задать только один дискриминатор на всех через общий конфиг

Все эти изменения касаются формата JSON. А в HOCON поправили совместимость с JVM 1.8.
Добавлял в приложение поле ввода для номера телефона, как положено выставил ему autofillHints="phoneNumber" и стало интересно почему у меня автозаполнение номера телефона не работает.

Сервис автозаполнения в настройках выбран от гугла. Он умеет подставлять номера телефонов, но не понятно откуда берёт номера для подстановки. Методом научного тыка выяснил, что не из профиля Google и не из списка контактов, а значит остаётся вариант "с SIM-карты".

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

К счастью, номер можно добавить в SIM-карту через AT-команды, но потребуется root и ADB. Написал гайд по горячим следам, если вдруг захотите повторить мои шаги.

#guide
Обновления!

Актуализировали kotlin-style-guide в публичном репозитории:
• удалили правила, которые дублировали рекомендации оффициального гайда от JetBrains
• часть правил убрали, часть изменили, добавили новые (особенно про именованные аргументы)
• везде поправили примеры и их форматирование

Да, знаю, что так себе changelog, но изменений слишком много, чтобы все их описывать телеге и проще посмотреть дифф. Сейчас занимаюсь настройкой синхронизации нашего внутреннего репозитория с публичным и если всё получится, изменения в style-guide будут прилетать порционными коммитами.

Несколько обновлений залетело в redmadrobot-android-ktx.
• В resources-ktx появились новые экстеншены для получения значений из атрибутов - Context.resolveDimension, Context.resolveBoolean и т.д.
А ещё в пару к getString добавили экстеншен getQuantityString для View и Fragment.
• В core-ktx добавили экстеншен Canvas.withClipOut и внесли изменения в делегаты SharedPreferences.
• В fragment-args-ktx прилетели фиксы для ленивого вычисления значений по умолчанию и одно ломающее изменение. Постарался оставить deprecated функции для миграции, но не очень хорошо получилось, будьте осторожны при обновлении.

#oss
Тут в рабочем чатике закинули книжку "Jetpack Compose internals" которая объясняет как же вся эта магия работает под капотом от компиляции до рантайма.
По ссылке можно как купить книжку, так и скачать бесплатно — вам решать.
Автор Jorge Castillo, GDE по Android и Kotlin.

#book #android #compose #ui
Только недавно наткнулся на Typography в стандартной библиотеке Kotlin, хотя он добавлен в 1.0, а может и раньше.
Теперь можно поудалять свои константы, а новые символы добавлять прямо в этот object как inline extension-поля.

#kotlin
Google обещал что DataStore можно будет шифровать, но пока не предоставил никакого решения. Чтобы переждать до момента когда такое решение появится, набросал микро-библиотеку которая позволяет добавить шифрование к сериализаторам DataStore.

Основная сложность была — шифровать PreferenceDataStore т.к. у него и конструктор, и сериализатор internal и возможности кастомизации ограничены. Благо можно хакнуть видимость через Javа-код, что мне и пришлось сделать.

#androidx