We Love Android – Telegram
We Love Android
635 subscribers
259 photos
26 videos
4 files
630 links
Новости из мира Android-разработки
Download Telegram
AboutLibraries автоматически собирает все зависимости и лицензии Gradle-проекта и предоставляет легко интегрируемые UI-компоненты для сред Android и Compose. Делает это во время компиляции и предлагает простые API для их визуализации в приложении. Никаких накладных расходов во время выполнения. Сильное кэширование. Поддерживаются любые gradle-зависимости. Поддерживает Kotlin Multiplatform.

AboutLibraries на GitHub: https://github.com/mikepenz/AboutLibraries
Платформа: Android
⭐️: 3.5K
👍3🔥2
Продолжаю рубрику #насмотренность. Сегодня смотрим на inline-классы. На мой взгляд это одна из самый недооценённых фичей Котлина. Подозреваю, что это потому что потребность в inline-классах неочевидна. Попробую это исправить.

Напомню. Inline-класс это обёртка над другим типом. Он должен иметь строго один параметр в основном конструкторе — значение которое мы оборачиваем. При компиляции вместо нашего класса будет подставлено обёрнутое значение. То есть класс есть, а лишних аллокаций нет. Красота!

Минутка духоты: На самом деле обёрнутое значение не всегда будет инлайниться. Принцип работы похож на (un)boxing примитивов. Но это тема для отдельного поста.

1️⃣ Объявление собственных примитивов

Примитивные типы это то, что должно работать быстро. Мы ожидаем, что примитивы передаются по значению, то есть для них не создаётся объект в куче. Звучит как работа для inline-класса, ведь если в него завернуть примитив, то и перформанс получим как у примитива.

За примером далеко ходить не надо — UInt и другие беззнаковые типы в Kotlin это inline-классы. Но вот где действительно разгулялись с примитивами, так это в Jetpack Compose. Цвета раньше передавались либо как Int в формате 0xAARRGGBB, либо как класс, теперь же Color это inline-class. Получаем все удобства класса и легковесность примитива. Кроме цветов есть ещё Dp, Size, Offset и т.д. (для типов, состоящих их нескольких свойств, например Size, под капотом используется упаковка данных в один примитив). Так что, если вас как и меня мучил вопрос почему нет ничего страшного в том, что мы на каждой рекомпозиции создаём объекты, это потому что на самом деле никаких объектов нет.

2️⃣ Дешевые enum'ы

Помните совет гугла заменять enum'ы на Int с аннотацией @IntDef? Потом Jake Wharton рассказал, что R8 умеет оптимизировать enum'ы и мы выдохнули.
Так вот если всё-таки нужно заменить enum на примитив, inline-классы помогут обойтись без сомнительных конструкций с @IntDef, которые опираются только на стат. анализ.

Примеры этого подхода, опять же, можно посмотреть в Compose: TextAlign , TextOverflow и LineBreak. Да, к сожалению, при таком подходе в when нет проверки, что покрыты все ветви, но на этот компромисс я готов пойти.

3️⃣ Обёртки

Наиболее частое применение inline-классов — создание обёрток над другими типами, чтобы:
👉 Получить более строгую типизацию. Например, чтобы не ошибиться когда у нас много ID-шников одинакового типа у разных сущностей. Или более явно указать в сигнатуре функции, что "этот параметр должен быть не какой угодно строкой, а именно номером телефона". Это работает благодаря важному свойству inline-классов, что их нельзя сравнивать с другими типами. Попытка такого сравнения выкинет ошибку на этапе компиляции.
👉 Сузить скоуп для утилитарных функций. Вот есть у нас номер карты пользователя в формате строки. Мы хотим делать с этим номером много всякого: форматировать группами по 4 цифры, вывести маскированный номер карты вида *1234 и т.д. Можно сделать кучу экстеншенов на String, которые будут видны когда нужно и когда не нужно, а можно завести inline-класс и явно определить что с ним можно делать.
👉 Добавить новые свойства обёртнутой сущности. Добавить @Immutable ко спискам? Запросто.

Напоследок пример где и типизация важна, и новые свойства добавляются. Помните как в onMeasure нам прилетают Int'ы, с которыми нужно работать исключительно через утилитарный класс MeasureSpec? В Compose вместо этого прилетает один класс Constraints и мы сразу, без похода в документацию, понимаем набор действий, который можно совершать с этим классом. Ну не красота ли?
👍7🔥4🤔2
Forwarded from Mobile AppSec World (Yury Shabalin)
Make drozer great again

Не могу пройти мимо этой новости, спустя 7 долгих лет произошло обновление любимого многими инструмента drozer

Теперь он поддерживает python3! И очень надеюсь на добавление нового функционала.

Плюс, авторы обновили и репо с уязвимым приложением, которое показывает основные уязвимости Android приложений.
Ну и небольшое прохождение, которое показывает возможности drozer.

Пока что не поддерживается запуск на Windows и есть определенные проблемы со стабильностью в ряде случаев, но все равно это по настоящему возрождение легенды :)

#drozer #android
👍3🔥1💩1
Forwarded from Mobile Developer (Алексей Гладков)
Как избавиться от лишнего кода в build.gradle [EN]
https://proandroiddev.com/how-to-get-rid-of-boilerplate-code-in-build-gradle-files-7bfac83ca1c8

👉 Что можно вынести в settings.gradle
👉 Как написать convention plugin
👉 Практический совет на примере
👍1🔥1
Я веду бэклог постов и в рубрике #насмотренность следующий пост должен был быть про функции-конструкторы. Но иногда нужно просто немного подождать и кто-то сделает все за тебя :) На хабре вышла статья "Конструкторы-самозванцы в Kotlin", где автор описывает варианты мимикрии функций под синтаксис конструктора и в каких случаях это может понадобиться. Спасибо ему! Мне остаётся только досыпать примеров использования в Open Source.

1️⃣ Функция-конструктор
Это просто функция высшего порядка, написаная с большой буквы, которая внутри создаёт и возвращает инстанс класса.
Полезно, если хочется дать возможность "создавать инстанс интерфейса". Объявляете интерфейс, кладёте рядом с ним функцию с таким же названием и готово, даже импортировать её отдельно не придётся. Реализация интерфейса при этом может остаться приватной. Вызовы MutableStateFlow и MutableSharedFlow в корутинах, Json в kotlinx.serialization это всё вызовы таких функций. Это помогает уменьшить API-surface, а значит упростить использование API.
Ещё один вариант использования — вместе с inline-классами. Например, у Size в Compose конструктор помечен как internal, а "создание инстанса" происходит через функцию c двумя параметрами.

2️⃣ Перегрузка Companion.invoke
Причины применения указанные в статье (контроль над созданием объекта, создание пула объектов, кэширование и т.д.) классные, но нужны примеры. Пример контроля над созданием объекта можно увидеть в PlatformVersion в ktor. То есть в зависимости от определённой логики мы можем мы либо создаём инстанс, либо возвращаем какой-то существующий.
Но часто применение более банальное — вместо вторичного конструктора. Тут я могу только догадываться почему не используется вторичный конструктор, но примеры такого применения можно увидеть в RuleSet из detekt и MockEngine из ktor. Иногда применение вместо вторичного конструктора можно оправдать тем, что логики для подготовки параметров конструктора очень много. Например в SpriteAnimation из korge (игровой движок на Kotlin).

3️⃣ <Context>.invoke()
То же самое, что предыдущий вариант, но для случая когда нужно ограничить применение invoke контекстом.
В дикой природе этот вариант я не встречал, но сам автор даёт пример применения в yatagan и рассказывает в статье зачем это понадобилось. После выхода context parameters (следующая итерация context receiver'ов) этот вариант будет выглядеть приятнее.

🤔 Как относиться к такому?
Я часто вижу хейт в сторону подобных конструкций, мол мимикрия и переопределение операторов это зло, так как порождает неявность. Да, на самом деле вызывается не конструктор, а функция, но что в этом плохого если она выполняет ту же смысловую нагрузку? Уверен, многие с чистой совестью вызывают MutableStateFlow и им не важно, что под капотом. Главное следовать принципу наименьшего удивления. Если что-то выглядит как конструктор, оно и работать должно как конструктор.
Накидайте аргументов если я не прав!

#kotlin
👍2🔥1
Forwarded from Kotlin Multiplatform (Kostya)
https://github.com/ShreyashKore/wonderous_compose

Я уже упоминал этот проект как-то раз. Очень красиво и работает на всех возможных платформах! (не надо только пробовать веб версию на мобильных устройствах)
А теперь там появились встроенные карты на всех платформах - стоит изучить 😉
3🔥3👍1
Forwarded from Mobile Compose
#Предложка #Libs #Compose

Compose Color Preview

Наверняка вы замечали, что при работе с Compose Multiplatform в IntelliJ IDEA нет привычных превью цветов в панели слева. Одним из решений этой проблемы является Compose Color Preview — плагин, автором которого является один из подписчиков канала. Однозначно лайк 👍
👍8🔥3
🔥‼️🔥 Вышел Kotlin 2.0 🔥‼️🔥

#k2 #kotlin2
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥161
Fleet - официально IDE для KMP разработки

#kotlinconf #ide #fleet
6🤮2👍1
Forwarded from iOS Makes Me Hate (Lev Bondarenko)
Как решать задачи на литкод

Какое-то монументальное видео, где чувак 4,5 часа выдает базу. Супер нишевый видос, когда автор просто на своем желании сделал офигенную лекцию, уровня которой не найдешь на ютубе. А где-то даже заменит целые курсы по алгосам от яндекса и тп.

Разобрав такие острые вопросы:
🟣чем отличаются problem solving skills от заучивания алгоритмов
🟣какие алгоритмы нужны и как начать понимать их пользу
🟣почему большинство ошибается насчет бесполезности алгоритмов
🟣работа с когнитивными искажениями и ментальными барьерами
🟣ментальная гигиена и как не выгореть от неудач

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

Пожелайте счастья таким людям, кто просто делает крутой контент для себя. Очень вайбовый видос, который смотришь на одном дыхании.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍2
Forwarded from Mobile Developer (Алексей Гладков)
Coroutines Essentials [EN]
https://typealias.com/start/kotlin-coroutines/

Еще одна статья, которая разжевывает прям в мелочах, как именно работают корутины во всех деталях

👉 Что такое многопоточность
👉 Как корутины реализуют concurrency
👉 Внутренняя машинерия
👉 Реальные примеры

Все весело, задорно, с картинками и игровыми механиками. В общем, если после этого рассказа все еще не понятно что такое корутины, то в следующем посте я скину вакансии из Вкусно и точки
👍5🔥1
Forwarded from Mobile AppSec World (Yury Shabalin)
Небольшая статья, которая поможет разобраться в разнообразии *links в Android

Всем привет!

Давно меня не было слышно, очень-очень плотно работа забрала себе :D
Но все-таки, хочется немного порадовать себя и вас. Сегодня у нас вышла новая статья по механизмам работы WebLinks, AppLinks и DeepLinks в Android. Я очень часто их путал и до конца не понимал, а в чем же отличие одного механизма от другого.

И наконец-то, совместно с @veselinaz до конца разобрались, что это и с чем едят.

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

Очень надеюсь, вам понравится!

Приятного чтения!
🧬 Все каналы по мобильной разработке

Собрал тут кажется самую большую коллекцию:


🌸Android — авторский контент об Android

🌸iOS — авторский контент об iOS

🌸Компании — bigtech-компании и организации

🌸Подборки/новости/библиотеки


@dolgo_polo_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥32
Forwarded from Android Live 🤖
When и Guard Conditions
#kotlin

С релизом Kotlin 2.1.0 появился апдейт для when — guard conditions. Эта новая фича улучшает читаемость кода, делая его более наглядным.
Давайте рассмотрим на примере, что она делает.

Предположим, есть базовый класс для получения ответа от сервера:

sealed interface HttpResult {
data class Success(val response: String) : HttpResult
data class Failed(val statusCode: Int) : HttpResult
}


Если включить Guard Conditions, то проверка в when специальных юзкейсов будет выглядеть так:

when (response) {
is HttpResult.Success -> println("Success")
is HttpResult.Failed if response.statusCode == 503 -> println("Maintenance")
is HttpResult.Failed -> println("Failed with code ${response.statusCode}")
}


Как мы видим, одну ошибку от бэка мы обработали без добавления if внутри условия:

when (response) {
is HttpResult.Success -> println("Success")
is HttpResult.Failed -> {
if (response.statusCode == 503) {
println("Maintenance")
} else {
println("Failed with code ${response.statusCode}")
}
}
}


Похоже, что стало удобнее, но нужно попробовать на практике.
Чтобы включить фичу, надо убедиться, что K2 Compiler включен, а потом добавить опцию:

kotlin {
compilerOptions {
freeCompilerArgs.add("-Xwhen-guards")
}
}


Чуть больше информации можно найти тут.
🔥71
Forwarded from Mobile Compose
#Tip #Compose

💡 Знаете ли вы?

Compose имеет встроенную функцию LoremIpsum, которая поможет сгенерировать вам тестовую строку необходимой длины для Preview и сэкономить вам время при разработке.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥1