Telegram Web
​​Clipt

Совсем недавно мне приходилось тестировать фичу, в которой важно было постоянно копировать текст с Mac на Android-устройство.

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

Немного погуглив, нашёл решение, которое, возможно, пригодится и вам.
Есть плагин для Google Chrome, который называется Clipt. Сначала устанавливаете плагин и приложение на Android, потом через учётную запись Google связываете два устройства, чуть настраиваете то, когда и что надо копировать, и вот у вас общий буфер обмена. 🙌🏻
👍9🤯3
​​Android 12: Data Access Rationale
#android

В Android 12 появилась фича под названием Data Access Rationale. Далеко не все разработчики используют её в своих приложениях, хотя штука довольно важная.

По сути, это Activity, которая даёт информацию пользователю о том, для чего нужно то или иное разрешение. Её можно открыть в информации о приложении прямо из системы, а также в Privacy Dashboard.

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

Кажется, что это действительно важный и логичный шаг в прозрачности использования фич, требующих разрешение: не всегда понятно, почему приложение запрашивает доступ к той или иной фиче, а подобное объяснение здорово повысит лояльность пользователя. 🤞🏻
👍10🤔4
​​Как измерить производительность Compose?
#compose

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

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

Итоговый отчёт работает в релизном билде и состоит из нескольких файлов:
• общая статистика по приложению;
• детальная статистика по каждой из функциий;
• csv-версия этой же статистики;
• информация о стабильности каждой из написанных функций.

Каждый раз мы получаем информацию о нескольких параметрах: Restartable, Skippable, Immutability & stability. Дальше, смотря на эти параметры, мы можем понять, что можно улучшить: например, если функция restartable, но не skippable, то стоит посмотреть, какие параметры являются входящими в эту функцию и почему компилятор считает некоторые из них unstable.

Пока что статистика выглядит не самой простой для понимания, но первый шаг сделан. Так что ожидаем больше статистики и более удобный вид для анализа тех данных, что у нас есть.
👍4
​​Flow под капотом
#flow

Отличная статья, которая показывает то, как устроен Flow под капотом.

Автор утверждает, что сама концепция Flow — проще, чем многие разработчики думают: под капотом описано много простых механизмов, которые после объединения и выдают то, что мы привыкли видеть при использовании Flow.

Для понимания всего, автор делает несколько простой лямбда-функции, которую, постепенно усложняя, превращает в подобие того, что мы видим во Flow.
👍15🔥4
​​KMM — UI State management
#kmm

Классный цикл статей, где автор рассматривает управление состоянием View при помощи архитектуры MVI, причём и на iOS и на Android при помощи KMM.

В первой статье автор рассказывает о базовых принципах MVI и вводит те понятия, которые там используются: State, Event, SideEffect, а также делает базовую инмплементацию на примере простенького приложения. Будет полезно, если вы не очень хорошо знакомы с MVI.

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

Код супер простой и понятный, что будет полезно новичкам, которые только изучают KMM. 🤓
👍10🤩3
​​Равенство объектов в Java и Kotlin
#kotlin

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

Наиболее интересно посмотреть на кейсы, где разные подходы к проверке на равенство могут привести к плохим результатам.
Например, в Java надо быть внимательным при наследовании одного объекта от другого и их дальнейшего сравнения: в этом случае не равные по сути объекты могут оказаться равными по функции equals(). Любопытен и тот факт, что функция сравнения часто может оказаться менее производительной, чем кажется на первый взгляд.

В Kotlin было интересно посмотреть про кейс использования массивов в data-классах.

Пара выводов из этой статьи:

1️⃣ Проверьте, можно ли обойтись без переопределения функций equals/hashCode. Это может помочь в производительности сравнения функций.

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

3️⃣ Если не получается использовать принцип Composition over inheritance, то проверьте правильность использования функций equals в абстрактном и наследуемом классах.
👍12
​​Testing Kotlin coroutines on Android
#tests

При тестировании coroutines требуются некоторые изменения в написании тестов, ведь сами функции могут выполняться асинхронно.
Для того, чтобы лучше понять, как тестировать код с coroutines есть неплохой гайд от Google, где описываются несколько интересных моментов, которые стоит учитывать.

Для тестов нужно добавить специальную зависимость kotlinx.coroutines.test, после которой становятся доступными сразу несколько полезных функций.
Например, функция runTest позволяет обернуть существующий код на coroutines и выполнить его.

Кроме этого, добавляются тестовые Dispatchers, которые используются только в тестах. В статье описывается, какие типы существуют, а также как корректно применить их к существующему коду.
👍5👏1
​​Переменные при сборке проекта

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

1️⃣ Дано: некая переменная, которая может меняться в зависимости от разных билдов.

2️⃣ Заводим эту переменную в build.gradle и прописываем ей дефолтное значение, например:
def isVariable = false

3️⃣ Дальше добавляем проверку на наличие этой переменной в свойствах, которые будем передавать в командной строке при сборке.
if (project.hasProperty('isVariable')) {
isVariable = project.property('isVariable').toBoolean()
}


Саму переменную можно прокинуть в buildConfigField для того, чтобы видеть её из кода.

4️⃣ Начинаем сборку билда и передаём нужную нам переменную. По желанию, их может быть несколько.
./gradlew assembleQaRelease -PisVariable=true.

На этом, в целом всё, может быть и эта фича будет кому-то полезна. 🤓
👍11🔥5🤔4
​​Отмена долгих операций
#coroutines #kotlin

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

В качестве примера были взяты Coroutines, что здорово.
Даже если в проекте вам не обязательно делать все операции отменяемыми, автор довольно годно рассматривает различные состоятия Coroutines, какое поведение будет при отмене, если имеются дочерние задачи, да и в целом, как сделать отмену контролируемой. 👌🏻
👍121
Тут в голове родилась одна идея, но прежде реализации, хотел бы узнать:

Какие сервисы вы используете для прослушивания подкастов?
Anonymous Poll
42%
Yandex Music
10%
Apple Podcasts
29%
Google Podcasts
9%
Soundcloud
3%
Castbox
20%
Spotify
13%
Другое (напишу в комментариях)
🤮11👍3🤔3🔥1
​​Koin 3.2 - New DSL
#koin

Тут совсем недавно вышло крутое обновление библиотеки Koin, которое позволяет гораздо проще настраивать сам Koin — Constructor DSL.

Раньше типичный модуль в Koin выглядел следующим образом:

class MyClassA()
class MyClassB(val a : MyClassA)

// Let Koin find dependencies for you with get()
module {
single { MyClassA() }
single { MyClassB(get()) }
}


Как видно, в MyClassB нужно добавить get() по количеству параметров, которые в этот класс передаются. Если таких параметров будет много, то и число этих get() будет кратно увеличиваться.

В новой же версии мы получаем более удобную структуру:

class MyClassA(val id : String)

module {
singleOf(::MyClassA)
}

// in calling code
val classA : MyClassA by inject { parametersOf("_id_")}


То есть теперь все вызовы get() останутся в прошлом, и мы получим гораздо более красивый и читаемый код.
Больше примеров кода и инфа о других изменениях по ссылке.
👍202
​​Kotlin Contracts
#kotlin

Не очень часто используемой, но интересной и полезной фичей являются Contracts.

Основная цель контрактов — помочь компилятору Kotlin в анализе кода в случаях, когда разработчик знает о коде больше деталей, чем может увидеть компилятор.

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

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

Будет круто, если поделитесь своими примерами использования этой фичи в своих проектах.
👍14💩1
​​Gradle version catalogs
#gradle

Если ваш проект состоит из одного модуля, то управление зависимостями — довольно простая задача. Но как только вы переходите на многомодульность, то всё становится несколько сложнее.

Есть несколько вариантов решения этой задачи:
1️⃣ Управлять вручную — в каждом из модулей у вас будут повторяться те библиотеки, которые вы добавляете. Думаю, что нет смысла говорить, что этот подход не очень хороший.

2️⃣ Блок ext — подход, которым часто пользуется сам Google, и который как раз решает проблему из первого пункта. Правда в таком случае нет автозаполнения кода при написании.

3️⃣ buildSrc — можно использовать специальный gradle-модуль, где как раз и описать эти зависимости.

Но есть ещё один, менее известный, но очень удобный подход — это Version Catalogs. Он доступен в версии Gradle 7.4, и очень удобно описывает все зависимости проекта.

Подробная инструкция с тем, как всё добавить к себе тут.

Android Studio поддерживает этот формат файлов, а ещё есть плагин, который перенесёт задачу обновления компонентов на CI. 🤓
10💩1
​​Тесты для уведомлений
#android #tests

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

Вообще, если в проекте и пишутся тесты, то нотификациям уделяется совсем мало внимания: иногда создаётся интерфейс, который мОкается в тестах, но который при этом не имеет отношения непосредственно к показу этих уведомлений.

Автор делится своим опытом, как корректно подключить NotificationManager, как проверить, какое действие выполнилось при открытии пуша, и показывает в реальном приложении написанные для уведомлений тесты.
👍14👎2
​​Material You в Jetpack Compose
#design #compose

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

Попалась любопытная статья, где автор применяет библиотеку Material Design 3 к своему небольшому приложению, написанному на Compose.
Тут можно подсмотреть, как лучше хранить цвета и ресурсы для тем в Compose, как лучше сделать динамические темы, да и то, как начать переезд на эту фичу в своём приложении.

Выглядит здорово, надеюсь на поддержку этой фичи в основных приложениях.
6👍3👎1
​​Как мы уменьшили ANR в 3 раза
#android

Ошибка "Приложение не отвечает" — весьма неприятное событие для пользователя, ведь в этом случае он вынужден закрывать приложение и делать незавершённое действие с начала.
Кроме этого, эти ошибки довольно непросто повторить и поправить, ведь они могут то появляться, то исчезать, а также иметь зависимость от устройств.

Вот неплохая статья, которая описывает то, откуда вообще появляются ANR и то, как с ними бороться.
Автор говорит, что они ощутимо снизили процент этих ошибок в своём приложении, а также значительно улучшили время старта приложения.
👍8👎31
​​Parallax Effect в Jetpack Compose
#compose

Попалась красивая реализация эффекта параллакса, которая написана на Jetpack Compose.
Не уверен на 100%, что вам есть где использовать этот эффект в приложении, но любопытно посмотреть на саму реализацию. Тем более, на столь популярном в последнее время Compose.

@Composable элементы меняют своё положение на основе ориентации устройства и приходящих данных с SensorManager. Далее, создаётся DisposableEffect, который используется для репозиционирования Image.

Автор добавил немного модификаторов для тени и карточки. В итоге получился приятный и красивый эффект.
Чуть больше деталей реализации, ну и, конечно, примеры кода можно найти тут. 🤓
👍9👎1
​​How to write the best Usecase/Interactors ever!
#android

Попалась на глаза неплохая статья, которая рассказывает о принципах написания корректных UseCases. Если вы совсем не знакомы с тем, что это за слой архитектуры, то стоит ознакомиться с этой статьёй.

ℹ️ ВообщеUseCase — весьма полезный класс, который сильно облегчает взаимодействие между Repository и ViewModel. Правда, существует много разных подходов, связанных с корректным управлением жизненным циклом этого UseCase.

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

🖖 Идея с CoroutinesUseCaseRunner удобная, так что рекомендую попробовать подобный подход в своих проектах.
👍111
Жизнь в ОАЭ
#интервью #экспаты

Давненько на канале не выходили интервью с разработчиками, которые переехали жить и работать в другие страны.
Думаю большинство из вас видели анонс про ОАЭ. Но, виноват. Сильно задержал публикацию, хотя само интервью уже было готово.

Однако теперь всё отредактировано и его уже можно почитать тут. В комментариях можете задавать дополнительные вопросы автору, если они появятся.
Кстати, Антон тоже ведёт свой Telegram канал как раз про жизнь в Дубае, так что подписывайтесь, если вам интересна эта тема. 🇦🇪

Ну и до следующих анонсов новых стран, уже есть парочку идей😉
🔥133👎2👍1
2025/08/26 19:34:49
Back to Top
HTML Embed Code: