Выпустил обновление 2.0-rc1 для mapmemory.
Эта библиотека позволяет быстро реализовать in-memory кэш.
Полностью release notes пересказывать не буду, но вот что хочется отметить:
- Теперь значения в MapMemory могут быть scoped и shared. Scoped ограничены к использованию только внутри класса где объявлены, shared можно шарить межу классами.
- Новый модуль
- Добавил поддержку RxJava 3
- Переписал README и KDoc комментарии. Жду комментов всё ли понятно теперь :)
- Упростил синтаксис для объявления nullable полей и полей со значением по умолчанию.
Гайд по миграции с v1.1 добавил в README.
#library
Эта библиотека позволяет быстро реализовать in-memory кэш.
Полностью release notes пересказывать не буду, но вот что хочется отметить:
- Теперь значения в MapMemory могут быть scoped и shared. Scoped ограничены к использованию только внутри класса где объявлены, shared можно шарить межу классами.
- Новый модуль
mapmemory-test с утилитами для удобного тестирования классов, использующих MapMemory.- Добавил поддержку RxJava 3
- Переписал README и KDoc комментарии. Жду комментов всё ли понятно теперь :)
- Упростил синтаксис для объявления nullable полей и полей со значением по умолчанию.
Гайд по миграции с v1.1 добавил в README.
#library
GitHub
Release v2.0-rc1 · RedMadRobot/mapmemory
Scoped and shared values (#1)
Now there are two types of memory values: scoped (to class) and shared.
All memory values by default are scoped to the class where it's declared.
Scoping prevents ...
Now there are two types of memory values: scoped (to class) and shared.
All memory values by default are scoped to the class where it's declared.
Scoping prevents ...
Что ж. Теперь точно пофиксили баг с утечкой фрагментов из Hilt
И в release notes к Dagger 2.34 он есть.
UPD: Пофиксили, но не доконца, а вот в 2.34.1 прям окончательно пофиксили. Честно-честно
И в release notes к Dagger 2.34 он есть.
UPD: Пофиксили, но не доконца, а вот в 2.34.1 прям окончательно пофиксили. Честно-честно
Telegram
Ra'Reilly
В Dagger 2.31.1 вошёл важный фикс Hilt, который почему-то не упомянули в Release Notes.
Вот он. Больше не будет утекать контекст фрагмента из-за Hilt.
UPD: Фикс ревертнули и он войдёт в 2.32
UPD2: Фикс так и не включили в 2.32, пока не понятно когда его…
Вот он. Больше не будет утекать контекст фрагмента из-за Hilt.
UPD: Фикс ревертнули и он войдёт в 2.32
UPD2: Фикс так и не включили в 2.32, пока не понятно когда его…
Пошёл на выходных обновить
Забавно в этом баге то как я пытался его воспроизвести, потому что он стрелял только в боевом проекте. Алгоритм воспроизведения довольно специфичный, поэтому в чистом проекте за несколько попыток воспроизвести не удалось.
Чтобы уж наверняка, скопировал весь рабочий проект и постепенно удалял из него всё лишнее, периодически пересобирая проект, чтобы убедиться, что баг не пропал. Получился около-бинарный поиск.
В итоге осталось три файлика и правильные настройки из которых смог слепить тестовый проект.
#bug #kotlin
mapmemory, но споткнулся о баг в котлине и не дошёл.Забавно в этом баге то как я пытался его воспроизвести, потому что он стрелял только в боевом проекте. Алгоритм воспроизведения довольно специфичный, поэтому в чистом проекте за несколько попыток воспроизвести не удалось.
Чтобы уж наверняка, скопировал весь рабочий проект и постепенно удалял из него всё лишнее, периодически пересобирая проект, чтобы убедиться, что баг не пропал. Получился около-бинарный поиск.
В итоге осталось три файлика и правильные настройки из которых смог слепить тестовый проект.
#bug #kotlin
YouTrack
KAPT: 'IllegalStateException: Couldn't find declaration file' on delegate with inline getValue operator : KT-46317
What steps will reproduce the issue? Environment: * Kotlin 1.4.32 (or 1.5.0-RC) * Gradle 6.8.3 * Java 11.0.10 Use the following code: import com.example.lib.Delegate // Condition 1. Use subclass from library class which has getValue operator class DelegateSubclass…
Если вы с одного устройства коммитите и в рабочий git-репозиторий, и в личный, наверняка были случаи, когда закоммитили код не с той почтой и именем.
И вот запушил что-то в рабочий проект с личного аккаунта, а потом сидишь и вычищаешь это через rebase перфекционизму ради.
Простой способ этого избежать — после того как стянул себе проект настроить всё что надо через
Более универсальный способ — использовать в глобальном
И вот запушил что-то в рабочий проект с личного аккаунта, а потом сидишь и вычищаешь это через rebase перфекционизму ради.
Простой способ этого избежать — после того как стянул себе проект настроить всё что надо через
git config. Если проектов много, а нужно настроить не только имя и email, но и ключ для подписи, например, это не удобно.Более универсальный способ — использовать в глобальном
.gitconfig настройку includeIf. Как можно понять из названия, эта настройка применит конфиги из другого файла, если выполняется условие. Синтаксис для определения условий достаточно ограниченный, но можно проверить в какой папке находится проект и в зависимости от этого применить настройки. У себя использую эту штуку так:[includeIf "gitdir:~/dev/rmr/"]В этом случае настройки из общего
path = .gitconfig.rmr
.gitconfig применяются ко всем проектам, а для проектов из папки dev/rmr/ некоторые настройки переопределяются в файле .gitconfig.rmr
#gitМожете считать, что меня только что разморозили, но я только вчера узнал про
Это альтернатива
submodule оставляет "метку", что "в этой папке должна лежать такая-то ревизия такого-то репозитория". Физически файлов из другого репозитория в вашем репозитории нет и чтобы они появились, нужно выполнить определённую команду. Наверное, это больше всего отпугивает от submodule — чтобы получить полностью рабочий репозиторий, недостаточно его клонировать, нужно ещё выполнить дополнительные действия.
subtree физически добавляет файлы из другого репозитория в ваш репозиторий вместе с историей коммитов. Процесс клонирования репозитория никак не меняется и другие разработчики могут не знать, что в проекте есть
Про
#git
git subtree.Это альтернатива
git submodule. Как и submodule, subtree позволяет подтянуть другой репозиторий внутрь вашего, но отличается подход.submodule оставляет "метку", что "в этой папке должна лежать такая-то ревизия такого-то репозитория". Физически файлов из другого репозитория в вашем репозитории нет и чтобы они появились, нужно выполнить определённую команду. Наверное, это больше всего отпугивает от submodule — чтобы получить полностью рабочий репозиторий, недостаточно его клонировать, нужно ещё выполнить дополнительные действия.
subtree физически добавляет файлы из другого репозитория в ваш репозиторий вместе с историей коммитов. Процесс клонирования репозитория никак не меняется и другие разработчики могут не знать, что в проекте есть
subtree. Файлы из "поддерева" можно изменять так же как с остальные файлы проектаПро
submodule должны знать все разработчики, а знать о subtree нужно только в момент когда хочется стянуть изменения из удалённого репозитория (pull) или наоборот запушить туда свои (push).# Добавляем удалённый репоизторий для subtreeP.S. Осталось научиться нормально синхронизировать файлы выборочно между репозиториями и будет совсем хорошо. Буду конфиги шарить направо и налево.
$ 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>
#git
Сегодня убил кучу времени на баг которого не существует.
В апишке есть метод, который возвращает
→ Запрос улетает
← Приходит ответ с кодом 500 (видно по логам)
... Приложение чего-то ждёт и запрос отваливается по таймауту.
Что? Да. Запрос, ответ на который уже вроде как пришёл отваливается по таймауту.
Отгадка отказалась проста. Ответ 204 не подразумевает тела и в нём нет заголовка
Мораль — перед тем как чинить, убедитесь, что оно сломано :) А если серьёзно, то внимательнее смотрите на запросы и ответы которые тестировщики делают частичной подменой данных.
В апишке есть метод, который возвращает
204 No Content. Тестировщик подменил код ответа на 500, чтобы проверить как приложение реагирует на ошибку и в результате получилось такое поведение:→ Запрос улетает
← Приходит ответ с кодом 500 (видно по логам)
... Приложение чего-то ждёт и запрос отваливается по таймауту.
Что? Да. Запрос, ответ на который уже вроде как пришёл отваливается по таймауту.
Отгадка отказалась проста. Ответ 204 не подразумевает тела и в нём нет заголовка
Content-Length, а вот для 500 тело может прийти и Content-Length должен быть определён. В результате у HTTP-клиента ломается мозг и он до таймаута ждёт пока ему долетят остатки ответа, которых не существует.Мораль — перед тем как чинить, убедитесь, что оно сломано :) А если серьёзно, то внимательнее смотрите на запросы и ответы которые тестировщики делают частичной подменой данных.
Московские роботы-андроиды* выкатываются на 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
Дебютное видео про всеми любимый 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
YouTube
Gradle "без боли" / Почему Kotlin DSL? / Пишем плагины - Осип Фаткуллин
Разбираемся для чего нужен Gradle, чем же плох Groovy и почему мы в red_mad_robot MSK переехали на Kotlin DSL. Разбираем какие есть неочевидные APIшки в Gradle про которые точно нужно знать если собираетесь писать плагины. А ещё будет много практики!
Первый…
Первый…
Оказывается, плагин
Причём работает эта штука достаточно умно — она в зависимости от вашего "окружения" выбирает что подключать:
НО если вы руками объявили зависимость
Конечно, оставили флажок на случай если вы не хотите полагаться на эту логику, а хотите просто отключить автоматическое добавление
Благодаря этим строчкам версия из
Ещё один способ выбрать общую версию Kotlin для всего проекта.
#kotlin #gradle
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
YouTrack
Add stdlib by default in source-sets : KT-38221
Motivation 1. Currently, the absolute majority of Kotlin projects require dependency on stdlib and almost non-functional without it 2. For multiplatform projects, we already have an inconsistency with native stdlib (which is added by default) 3. The issue…
Всё. Теперь не работают отговорки типа "на Android не принято заголовок по центру тулбара делать", "это системное поведение, его нельзя поменять". Теперь можно.
#ui
#ui
Через неделю - 27-го июля с утра буду выступать на Podlodka Android Crew с рассказом про Git.
Планирую рассказать много всего - про чистоту истории, атомарные коммиты, разные модели ветвления, как всё-таки заставить всех разработчиков следовать договорённостям. Еще хочу обзорно рассмотреть полезные функции - cherry-pick, patch, stash и т.д. и как это всё ложится на Android Studio (читай IntelliJ IDEA).
Думаю, что доклад будет слабо связан с Android, поэтому может быть интересен не только андроид-разработчикам. Ссылка на запись доклада появится на этом канале :)
#анонс #git
Планирую рассказать много всего - про чистоту истории, атомарные коммиты, разные модели ветвления, как всё-таки заставить всех разработчиков следовать договорённостям. Еще хочу обзорно рассмотреть полезные функции - cherry-pick, patch, stash и т.д. и как это всё ложится на Android Studio (читай IntelliJ IDEA).
Думаю, что доклад будет слабо связан с Android, поэтому может быть интересен не только андроид-разработчикам. Ссылка на запись доклада появится на этом канале :)
#анонс #git
podlodka.io
Онлайн-конференция Podlodka Android Crew, сезон #15
Недельное мероприятие от команды Podlodka: ежедневные интерактивные сессии в Zoom по актуальным проблемам Android-разработки, нон-стоп общение с экспертами и звёздами индустрии, закрытое профессиональное сообщество в Telegram.
Чтобы было не скучно ждать пока мы зальём что-то ещё на канал, появился плейлист "Это тоже мы". Туда я складываю выступления с площадок вне нашего канала (пока что все, хе-хе).
Как и обещал, добавил в этот плейлист ссылку на свой доклад про Git с подлодки. Там доступ по ссылке, поэтому если вы не купили билет, то посмотреть можно пока только с нашего канала.
В общем, по классике - подписывайтесь, ставьте лайки, рассказывайте друзьям и вот это всё :)
#rmr #анонс
Как и обещал, добавил в этот плейлист ссылку на свой доклад про Git с подлодки. Там доступ по ссылке, поэтому если вы не купили билет, то посмотреть можно пока только с нашего канала.
В общем, по классике - подписывайтесь, ставьте лайки, рассказывайте друзьям и вот это всё :)
#rmr #анонс
Просматривал исходники AGP 7.0.0 и заметил, что теперь папка
Вот этот коммит.
В release notes AGP этого изменения не нашел.
#kotlin #gradle
kotlin по умолчанию добавлена в source-set и больше не нужно делать это вручную, если подключён Kotlin Gradle Plugin.Вот этот коммит.
В release notes AGP этого изменения не нашел.
#kotlin #gradle
На нашем канале пока тихо, зато Саша Серебренникова (@serebrennik) записала для @android_broadcast аж сразу серию видео про Custom View! Я уже посмотрел два из трёх видео и всем советую — Саша нереально крутая. Наконец материал с нормальными примерами, а не "нарисуем зелёный треугольничек с красным квадратиком".
Ссылочку на плейлист уже добавил на канал, чтобы все наши выступления можно было найти в одном месте :)
#ui #анонс
Ссылочку на плейлист уже добавил на канал, чтобы все наши выступления можно было найти в одном месте :)
#ui #анонс
Довольно вкусный RC kotlinx.serialization подвезли!
- (Де)сериализация стримов -
- В конфиге появился флажок
- Теперь можно определять дискриминатор для классов по отдельности (для полиморфных типов). Раньше можно было задать только один дискриминатор на всех через общий конфиг
Все эти изменения касаются формата JSON. А в HOCON поправили совместимость с JVM 1.8.
- (Де)сериализация стримов -
Json.encodeToStream и Json.decodeFromStream- В конфиге появился флажок
explicitNulls с помощью которого можно отключить явную сериализацию null- Теперь можно определять дискриминатор для классов по отдельности (для полиморфных типов). Раньше можно было задать только один дискриминатор на всех через общий конфиг
Все эти изменения касаются формата JSON. А в HOCON поправили совместимость с JVM 1.8.
GitHub
Release 1.3.0-RC · Kotlin/kotlinx.serialization
This is a release candidate for the next version. It contains a lot of interesting features and improvements,
so we ask you to evaluate it and share your feedback.
Kotlin 1.5.30 is used by default....
so we ask you to evaluate it and share your feedback.
Kotlin 1.5.30 is used by default....
Добавлял в приложение поле ввода для номера телефона, как положено выставил ему
Сервис автозаполнения в настройках выбран от гугла. Он умеет подставлять номера телефонов, но не понятно откуда берёт номера для подстановки. Методом научного тыка выяснил, что не из профиля Google и не из списка контактов, а значит остаётся вариант "с SIM-карты".
Если в разделе "О телефоне" высвечивается номер телефона, то автозаполнение должно работать. В моём случае в поле "Номер телефона", было написано "Неизвестно". В этом поле отображается телефон, указанный в специальной секции телефонной книги сим-карты, в которой хранятся собственные номера. К сожалению операторы сотовой связи вольны не заполнять эту секцию, поэтому часто номер не будет отображаться.
К счастью, номер можно добавить в SIM-карту через AT-команды, но потребуется root и ADB. Написал гайд по горячим следам, если вдруг захотите повторить мои шаги.
#guide
autofillHints="phoneNumber" и стало интересно почему у меня автозаполнение номера телефона не работает.Сервис автозаполнения в настройках выбран от гугла. Он умеет подставлять номера телефонов, но не понятно откуда берёт номера для подстановки. Методом научного тыка выяснил, что не из профиля Google и не из списка контактов, а значит остаётся вариант "с SIM-карты".
Если в разделе "О телефоне" высвечивается номер телефона, то автозаполнение должно работать. В моём случае в поле "Номер телефона", было написано "Неизвестно". В этом поле отображается телефон, указанный в специальной секции телефонной книги сим-карты, в которой хранятся собственные номера. К сожалению операторы сотовой связи вольны не заполнять эту секцию, поэтому часто номер не будет отображаться.
К счастью, номер можно добавить в SIM-карту через AT-команды, но потребуется root и ADB. Написал гайд по горячим следам, если вдруг захотите повторить мои шаги.
#guide
Обновления!
Актуализировали kotlin-style-guide в публичном репозитории:
• удалили правила, которые дублировали рекомендации оффициального гайда от JetBrains
• часть правил убрали, часть изменили, добавили новые (особенно про именованные аргументы)
• везде поправили примеры и их форматирование
Да, знаю, что так себе changelog, но изменений слишком много, чтобы все их описывать телеге и проще посмотреть дифф. Сейчас занимаюсь настройкой синхронизации нашего внутреннего репозитория с публичным и если всё получится, изменения в style-guide будут прилетать порционными коммитами.
Несколько обновлений залетело в redmadrobot-android-ktx.
• В resources-ktx появились новые экстеншены для получения значений из атрибутов -
А ещё в пару к
• В core-ktx добавили экстеншен
• В fragment-args-ktx прилетели фиксы для ленивого вычисления значений по умолчанию и одно ломающее изменение. Постарался оставить deprecated функции для миграции, но не очень хорошо получилось, будьте осторожны при обновлении.
#oss
Актуализировали 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
GitHub
GitHub - RedMadRobot/style-guides: red_mad_robot Style Guides
red_mad_robot Style Guides. Contribute to RedMadRobot/style-guides development by creating an account on GitHub.
Тут в рабочем чатике закинули книжку "Jetpack Compose internals" которая объясняет как же вся эта магия работает под капотом от компиляции до рантайма.
По ссылке можно как купить книжку, так и скачать бесплатно — вам решать.
Автор Jorge Castillo, GDE по Android и Kotlin.
#book #android #compose #ui
По ссылке можно как купить книжку, так и скачать бесплатно — вам решать.
Автор Jorge Castillo, GDE по Android и Kotlin.
#book #android #compose #ui
Leanpub
Jetpack Compose internals
This book consciously explores the guts of Jetpack Compose, the brand new library by Google and the Android team that will become the future of Android UI.
Только недавно наткнулся на Typography в стандартной библиотеке Kotlin, хотя он добавлен в 1.0, а может и раньше.
Теперь можно поудалять свои константы, а новые символы добавлять прямо в этот object как inline extension-поля.
#kotlin
Теперь можно поудалять свои константы, а новые символы добавлять прямо в этот object как inline extension-поля.
#kotlin
Google обещал что DataStore можно будет шифровать, но пока не предоставил никакого решения. Чтобы переждать до момента когда такое решение появится, набросал микро-библиотеку которая позволяет добавить шифрование к сериализаторам DataStore.
Основная сложность была — шифровать
#androidx
Основная сложность была — шифровать
PreferenceDataStore т.к. у него и конструктор, и сериализатор internal и возможности кастомизации ограничены. Благо можно хакнуть видимость через Javа-код, что мне и пришлось сделать.#androidx
GitHub
GitHub - osipxd/encrypted-datastore: Extensions to store DataStore in EncryptedFile
Extensions to store DataStore in EncryptedFile. Contribute to osipxd/encrypted-datastore development by creating an account on GitHub.