Konfeature — библиотека на Kotlin для работы с удалённой конфигурацией фич
Работа с удалённой конфигурацией стала стандартной частью процесса разработки почти любого приложения. В зависимости от сложности могут потребоваться:
* удобный синтаксис для объявления элементов конфигурации
* возможность разделять конфигурацию по разным файлам для разных фич
* возможность использовать локальную конфигурацию на этапе активной разработки фич
* поддержка нескольких источников данных для удалённой конфигурации
* возможность просматривать список всех конфигураций и изменять их значения в целях отладки
* логирование значения и его источника при обращении к конфигурации, а также не‐критичных ошибок
Мы постарались учесть все эти требования при разработке Konfeature.
Установка
Использование
FeatureConfig
Определяет набор элементов конфигурации с помощью делегатов:
*
*
Регистрация конфигурации:
FeatureSource
Абстракция источника значений:
Пример для FirebaseRemoteConfig:
Добавление источника:
SourceSelectionStrategy
Позволяет гибко выбирать, из каких источников запрашивать значение:
Предопределённые стратегии:
*
*
*
https://github.com/RedMadRobot/Konfeature
✍️ @kotlin_lib
Работа с удалённой конфигурацией стала стандартной частью процесса разработки почти любого приложения. В зависимости от сложности могут потребоваться:
* удобный синтаксис для объявления элементов конфигурации
* возможность разделять конфигурацию по разным файлам для разных фич
* возможность использовать локальную конфигурацию на этапе активной разработки фич
* поддержка нескольких источников данных для удалённой конфигурации
* возможность просматривать список всех конфигураций и изменять их значения в целях отладки
* логирование значения и его источника при обращении к конфигурации, а также не‐критичных ошибок
Мы постарались учесть все эти требования при разработке Konfeature.
Установка
repositories {
mavenCentral()
}
dependencies {
implementation("com.redmadrobot.konfeature:konfeature:<версия>")
}
Использование
FeatureConfig
Определяет набор элементов конфигурации с помощью делегатов:
*
by toggle(...)
— для Boolean
*
by value(...)
— для остальных типов
class ProfileFeatureConfig : FeatureConfig(
name = "profile_feature_config",
description = "Конфигурация фич для профиля"
) {
val isProfileFeatureEnabled: Boolean by toggle(
key = "profile_feature",
description = "показывать точку входа в профиль",
defaultValue = false,
)
val profileFeatureTitle: String by value(
key = "profile_feature_title",
description = "заголовок кнопки профиля",
defaultValue = "Feature number nine",
sourceSelectionStrategy = SourceSelectionStrategy.Any
)
val profileButtonAppearDuration: Long by value(
key = "profile_button_appear_duration",
description = "длительность появления кнопки профиля в мс",
defaultValue = 200,
sourceSelectionStrategy = SourceSelectionStrategy.Any
)
}
Регистрация конфигурации:
val profileFeatureConfig = ProfileFeatureConfig()
val konfeatureInstance = konfeature {
register(profileFeatureConfig)
}
FeatureSource
Абстракция источника значений:
interface FeatureSource {
val name: String
fun get(key: String): Any?
}
Пример для FirebaseRemoteConfig:
class FirebaseFeatureSource(
private val remoteConfig: FirebaseRemoteConfig
) : FeatureSource {
override val name: String = "FirebaseRemoteConfig"
override fun get(key: String): Any? {
return remoteConfig
.getValue(key)
.takeIf { source == FirebaseRemoteConfig.VALUE_SOURCE_REMOTE }
?.let { value ->
value.getOrNull { asBoolean() }
?: value.getOrNull { asString() }
?: value.getOrNull { asLong() }
?: value.getOrNull { asDouble() }
}
}
private fun FirebaseRemoteConfigValue.getOrNull(getter: FirebaseRemoteConfigValue.() -> Any?): Any? {
return try {
getter()
} catch (error: IllegalArgumentException) {
null
}
}
}
Добавление источника:
val konfeatureInstance = konfeature {
addSource(FirebaseFeatureSource(remoteConfig))
register(profileFeatureConfig)
}
SourceSelectionStrategy
Позволяет гибко выбирать, из каких источников запрашивать значение:
public interface SourceSelectionStrategy {
fun select(names: Set<String>): Set<String>
companion object {
val None: SourceSelectionStrategy = SourceSelectionStrategy { emptySet() }
val Any: SourceSelectionStrategy = SourceSelectionStrategy { it }
fun anyOf(vararg sources: String): SourceSelectionStrategy = SourceSelectionStrategy { sources.toSet() }
}
}
Предопределённые стратегии:
*
None
— всегда использовать только defaultValue
*
Any
— разрешает брать значения из любого источника*
anyOf("Source1", …)
— только из указанных источниковhttps://github.com/RedMadRobot/Konfeature
✍️ @kotlin_lib
👍3
Контракты в Kotlin или как заключить сделку с совестью
Всем привет, меня зовут Иван, я Android-разработчик и сегодня мы с вами поговорим об контрактах. Предвосхищая вопрос попробую сразу дать все ответы:
Контракты - это давний эксперимент языка Kotlin, какой смысл обозревать их сейчас, когда уже столько написано?
Нормальной статьи на русском языке я не обнаружил;
Я решил выбрать эту тему, так как мы сталкиваемся с контрактами в нашей повседневности, при этом не осознавая, как именно работает та или иная вещь;
Это моя первая проба пера и мне хотелось начать с чего-нибудь достаточно легкого, но при этом интересного.
https://habr.com/ru/articles/910924/
✍️ @kotlin_lib
Всем привет, меня зовут Иван, я Android-разработчик и сегодня мы с вами поговорим об контрактах. Предвосхищая вопрос попробую сразу дать все ответы:
Контракты - это давний эксперимент языка Kotlin, какой смысл обозревать их сейчас, когда уже столько написано?
Нормальной статьи на русском языке я не обнаружил;
Я решил выбрать эту тему, так как мы сталкиваемся с контрактами в нашей повседневности, при этом не осознавая, как именно работает та или иная вещь;
Это моя первая проба пера и мне хотелось начать с чего-нибудь достаточно легкого, но при этом интересного.
https://habr.com/ru/articles/910924/
✍️ @kotlin_lib
👍3
📚 Курс «Kotlin Backend Developer. Professional» — всё, что нужно для создания гибких и производительных приложений.
Что вы освоите:
Почему выбирают нас?
Не упустите шанс!
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Не используй use в Kotlin
Многие считают, что
В Java 7 для этого появилась конструкция try-with-resources, которая аккуратно складывает все исключения, а в Kotlin
Поэтому лучше явно закрывать ресурсы в
https://medium.com/@wn8yura/dont-use-use-in-kotlin-1005c9b6b9d4
✍️ @kotlin_lib
Многие считают, что
use
— это идеальный способ управления ресурсами в Kotlin, так как он автоматически закрывает ресурс после использования. Однако стоит быть осторожнее. Когда в блоке use
выбрасывается исключение, ресурс всё равно закроется, но если при закрытии произойдёт ещё одно исключение, то оно может затереть исходное, и ты потеряешь важную информацию о причине ошибки.В Java 7 для этого появилась конструкция try-with-resources, которая аккуратно складывает все исключения, а в Kotlin
use
реализован иначе. Например, если внутри блока работы с файлом что-то пошло не так, а потом и при закрытии возникла ошибка — ты увидишь только вторую, а первая просто исчезнет.Поэтому лучше явно закрывать ресурсы в
finally
, либо использовать Java-подход, если тебе важно не терять исключения.https://medium.com/@wn8yura/dont-use-use-in-kotlin-1005c9b6b9d4
✍️ @kotlin_lib
👍6🤣2
Заезжаем в Kotlin Multiplatform. Но какой ценой?
Этот доклад - текстовая версия моего выступления с осеннего Мобиуса 2024 года. Обязательно приложу видео с выступлением после выхода. А вот и оно.
О чем поговорим в статье:
Пройдем путь от идеи Kotlin Multiplatform до её реализации в цифрах.
Обсудим, сколько стоило внедрить Kotlin Multiplatform в продукты и к чему это привело.
Проведём ретроспективу: стоило ли это делать вообще и стоит ли инвестировать в эту технологию дальше. А также разберём, сколько это будет стоить в перспективе.
https://habr.com/ru/articles/887574/
✍️ @kotlin_lib
Этот доклад - текстовая версия моего выступления с осеннего Мобиуса 2024 года. Обязательно приложу видео с выступлением после выхода. А вот и оно.
О чем поговорим в статье:
Пройдем путь от идеи Kotlin Multiplatform до её реализации в цифрах.
Обсудим, сколько стоило внедрить Kotlin Multiplatform в продукты и к чему это привело.
Проведём ретроспективу: стоило ли это делать вообще и стоит ли инвестировать в эту технологию дальше. А также разберём, сколько это будет стоить в перспективе.
https://habr.com/ru/articles/887574/
✍️ @kotlin_lib
Не знаешь на кого пойти учиться ?💥
🛑 Пройди бесплатные онлайн-курсы
🛑 Узнай о самых востребованных профессиях
🛑 Получи уникальную возможность поступить в «Алабуга Политех» после 9 или 11 класса
ПРОЙДИ КУРС ПРЯМО СЕЙЧАС!
ПРОЙДИ КУРС ПРЯМО СЕЙЧАС!
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡1🔥1🍾1
Media is too big
VIEW IN TELEGRAM
Наглядный пример, когда не следовать best practices for coroutines от Google
Александр Таганов
Александр показал реальный пример из практики Т-Банка, когда следование best practices for coroutines ведет к проблемам. Объяснил, почему это происходит. Показад, чем еще занимается
00:00 - Про доклад
02:44 - Долгое ожидание простых операций
12:59 - Разбор причины долгих загрузок
21:30 - Выводы после анализа
24:35 - На что стоит заменить Dispatchers.Main
27:50 - Тестирование разных Dispatcher
источник
✍️ @kotlin_lib
Александр Таганов
Александр показал реальный пример из практики Т-Банка, когда следование best practices for coroutines ведет к проблемам. Объяснил, почему это происходит. Показад, чем еще занимается
main dispatcher
. И рассказал, как избежать подобных проблем00:00 - Про доклад
02:44 - Долгое ожидание простых операций
12:59 - Разбор причины долгих загрузок
21:30 - Выводы после анализа
24:35 - На что стоит заменить Dispatchers.Main
27:50 - Тестирование разных Dispatcher
источник
✍️ @kotlin_lib
👍3❤1
Почему не стоит использовать
🔸 В
🔸 Но
🔸 Из-за этого два объекта с одинаковыми массивами будут не равны:
🔸 Такая «ссылочная» проверка приводит к проблемам с коллекциями (
✅ Решение: вместо
Тогда
https://proandroiddev.com/avoid-using-array-in-the-data-class-constructor-in-kotlin-ebc308e46a95
✍️ @kotlin_lib
Array
в data class
Kotlin:🔸 В
data class
методы equals()
и hashCode()
генерируются автоматически на основе полей.🔸 Но
Array
в Kotlin (и Java) сравнивает не содержимое, а ссылки на объекты.🔸 Из-за этого два объекта с одинаковыми массивами будут не равны:
data class Person(val name: String, val friends: Array<String>)
val p1 = Person("Mike", arrayOf("Mary", "John", "Tom"))
val p2 = Person("Mike", arrayOf("Mary", "John", "Tom"))
println(p1 == p2) // false!
🔸 Такая «ссылочная» проверка приводит к проблемам с коллекциями (
HashSet
, HashMap
) и к «невидимым» багам: дубликаты, неверные кеш-промахи и т. д.✅ Решение: вместо
Array
используйте коллекции, которые сравнивают содержимое:
data class Person(val name: String, val friends: List<String>)
Тогда
equals()
проверит элементы списка по значению, и Person("Mike", listOf("Mary","John","Tom")) == Person("Mike", listOf("Mary","John","Tom"))
вернёт true
.https://proandroiddev.com/avoid-using-array-in-the-data-class-constructor-in-kotlin-ebc308e46a95
✍️ @kotlin_lib
👍4
🧩 Ktorfit — это библиотека, вдохновлённая Retrofit, для HTTP-клиентов на Ktor.
Она позволяет описывать HTTP-запросы с помощью аннотаций прямо в интерфейсах, как в Retrofit. Ktorfit использует KSP (Kotlin Symbol Processing) для генерации кода, поэтому не требует рефлексии и работает быстро.
🔧 Пример использования
Ktorfit создаёт реализацию интерфейса, которую можно использовать вот так:
📦 Особенности:
* Поддержка всех стандартных аннотаций:
* Полная интеграция с
* Генерация кода через KSP — высокая производительность
* Нет зависимости от Android
* Поддержка Kotlin Multiplatform
https://github.com/Foso/Ktorfit
✍️ @kotlin_lib
Она позволяет описывать HTTP-запросы с помощью аннотаций прямо в интерфейсах, как в Retrofit. Ktorfit использует KSP (Kotlin Symbol Processing) для генерации кода, поэтому не требует рефлексии и работает быстро.
🔧 Пример использования
@HttpApi
interface GitHubApi {
@GET("users/{user}/repos")
suspend fun listRepos(@Path("user") user: String): List<Repo>
}
Ktorfit создаёт реализацию интерфейса, которую можно использовать вот так:
val ktorfit = Ktorfit.Builder()
.baseUrl("https://api.github.com/")
.httpClient(HttpClient())
.build()
val api = ktorfit.create<GitHubApi>()
val repos = api.listRepos("Foso")
📦 Особенности:
* Поддержка всех стандартных аннотаций:
@GET
, @POST
, @Query
, @Path
, @Header
, и др.* Полная интеграция с
Ktor HttpClient
* Генерация кода через KSP — высокая производительность
* Нет зависимости от Android
* Поддержка Kotlin Multiplatform
https://github.com/Foso/Ktorfit
✍️ @kotlin_lib
👍5🥱5
Не хотите поговорить о Kotlin Contracts?
За время собеседований я заметил одну любопытную вещь: даже опытные котлиноводы частенько не в курсе такой мощной фичи, как Kotlin Contracts.
Этой серией статей я хочу простым человеческим языком показать, зачем нужны Contracts, как их использовать на практике и как они работают внутри.
Какую проблему решают Kotlin Contracts?
Все мы любим Kotlin за умные проверки типов. Например, напишешь так:
И всё работает!
Но стоит вынести ту же проверку в отдельную функцию:
В чём подвох?
https://habr.com/ru/companies/alfa/articles/916536/
✍️ @kotlin_lib
За время собеседований я заметил одну любопытную вещь: даже опытные котлиноводы частенько не в курсе такой мощной фичи, как Kotlin Contracts.
Этой серией статей я хочу простым человеческим языком показать, зачем нужны Contracts, как их использовать на практике и как они работают внутри.
Какую проблему решают Kotlin Contracts?
Все мы любим Kotlin за умные проверки типов. Например, напишешь так:
fun foo(x: Any) {
if (x is List<*>) {
x.size // Всё ок, компилятор молодец!
}
}
И всё работает!
Но стоит вынести ту же проверку в отдельную функцию:
fun isList(x: Any): Boolean = x is List<*>
fun foo(x: Any) {
if (isList(x)) {
x.size // Ошибка: "Unresolved reference: size"
}
}
В чём подвох?
https://habr.com/ru/companies/alfa/articles/916536/
✍️ @kotlin_lib
👍4
Media is too big
VIEW IN TELEGRAM
Klibs.io — the dream of creating a Kotlin Package Index
Ignat Beresnev
So you want to build a Kotlin package index.. What is a package anyway, is it the same as an artifact? What makes a project a library then? And why is it an index and not a repository?
источник
✍️ @kotlin_lib
Ignat Beresnev
So you want to build a Kotlin package index.. What is a package anyway, is it the same as an artifact? What makes a project a library then? And why is it an index and not a repository?
источник
✍️ @kotlin_lib
👍3
Media is too big
VIEW IN TELEGRAM
Подводные камни Kotlin Coroutines
Корутины не так уж сложно понять, когда вы разобрались с основами, но есть несколько подводных камней, которые могут сбить с толку. В сегодняшнем видео я поделюсь распространёнными ошибками, которые могут застать врасплох, если не быть внимательным.
✍️ @kotlin_lib
Корутины не так уж сложно понять, когда вы разобрались с основами, но есть несколько подводных камней, которые могут сбить с толку. В сегодняшнем видео я поделюсь распространёнными ошибками, которые могут застать врасплох, если не быть внимательным.
✍️ @kotlin_lib
👎5👍1🤡1
KotlinJS в GitHub Actions
GitHub Actions (GHA) — отличный инструмент для настройки CI/CD, а в GitHub Marketplace можно найти тысячи готовых GHA под любые задачи. Но всегда же найдётся процесс, который захочется настроить под себя. Тогда нам придётся написать кастомный GHA.
Привет! Это Макс Качинкин, Android Tech Lead в Додо. В этой статье я покажу, как создать свой GHA на Kotlin/JS, используя плагин Kotlin Multiplatform, и поделюсь готовым шаблоном в GitHub, с помощью которого вы сможете быстро написать собственный экшен на Kotlin/JS. Погнали!
https://habr.com/ru/companies/dododev/articles/898704/
✍️ @kotlin_lib
GitHub Actions (GHA) — отличный инструмент для настройки CI/CD, а в GitHub Marketplace можно найти тысячи готовых GHA под любые задачи. Но всегда же найдётся процесс, который захочется настроить под себя. Тогда нам придётся написать кастомный GHA.
Привет! Это Макс Качинкин, Android Tech Lead в Додо. В этой статье я покажу, как создать свой GHA на Kotlin/JS, используя плагин Kotlin Multiplatform, и поделюсь готовым шаблоном в GitHub, с помощью которого вы сможете быстро написать собственный экшен на Kotlin/JS. Погнали!
https://habr.com/ru/companies/dododev/articles/898704/
✍️ @kotlin_lib
👍5❤1
Вышел Kotlin Kotlin 2.2.20-Beta1
Released: July 10, 2025
https://kotlinlang.org/docs/whatsnew-eap.html
✍️ @kotlin_lib
Released: July 10, 2025
https://kotlinlang.org/docs/whatsnew-eap.html
✍️ @kotlin_lib
👍2
Актуальное повышение квалификации с курсом «Kotlin Backend Developer. Professional» от OTUS — это ваш шанс освоить современные практики и инструменты для масштабируемых серверных приложений. На курсе вы:
🗣 Преподаватели — практикующие эксперты, которые покажут реализацию проекта маркетплейса от идеи до продакшена. Программа постоянно обновляется в соответствии с требованиями рынка, а диплом OTUS ценится в крупных компаниях.
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Ныряем в холодные потоки Kotlin Flow
Лето — лучшее время для сплава. Поэтому, если вы пока не в отпуске, давайте устроим короткий сплав по асинхронным потокам данных.
Переход из привычной императивной парадигмы иногда бывает сложным, поэтому сначала поговорим о терминах.
https://habr.com/ru/articles/922962/
✍️ @kotlin_lib
Лето — лучшее время для сплава. Поэтому, если вы пока не в отпуске, давайте устроим короткий сплав по асинхронным потокам данных.
Переход из привычной императивной парадигмы иногда бывает сложным, поэтому сначала поговорим о терминах.
https://habr.com/ru/articles/922962/
✍️ @kotlin_lib
👍3
Media is too big
VIEW IN TELEGRAM
Эти фичи Kotlin меняют правила игры
0:00 Почему мы любим Kotlin
1:43 Новый долгожданный оператор
2:46 Розыгрыш книги с автографом Елизарова
4:09 Курс по OKT от АвитоТех
5:03 Обязательное использование возвращаемого результата (Must use return)
9:50 Прокачали работу с ошибками (не про исклоючения)
14:00 Куда скатился Kotlin... Много обещаний и...
источник
✍️ @kotlin_lib
0:00 Почему мы любим Kotlin
1:43 Новый долгожданный оператор
2:46 Розыгрыш книги с автографом Елизарова
4:09 Курс по OKT от АвитоТех
5:03 Обязательное использование возвращаемого результата (Must use return)
9:50 Прокачали работу с ошибками (не про исклоючения)
14:00 Куда скатился Kotlin... Много обещаний и...
источник
✍️ @kotlin_lib
👍3💩1
📲 Как сделать так, чтобы пользователи всегда возвращались туда, где они остановились в приложении?
⏺️ Присоединяйся к открытому вебинару «Flutter Deep Linking & State Restoration» 22 июля в 20:00 МСК. На вебинаре разберем:
— Типы диплинков во Flutter и как они работают с мобильными и веб-приложениями.
— Как выбрать правильную навигацию: Navigator 1.0 или Router API для сложных сценариев.
— State Restoration во Flutter: как сохранять и восстанавливать состояние после перезапуска.
— Использование Restorable Routes для автоматического возвращения на нужный экран.
❗️Этот вебинар — отличная тренировка перед стартом курса «Flutter Mobile Developer» от OTUS.
👉 Записаться на вебинар → https://vk.cc/cNLk8U
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
⏺️ Присоединяйся к открытому вебинару «Flutter Deep Linking & State Restoration» 22 июля в 20:00 МСК. На вебинаре разберем:
— Типы диплинков во Flutter и как они работают с мобильными и веб-приложениями.
— Как выбрать правильную навигацию: Navigator 1.0 или Router API для сложных сценариев.
— State Restoration во Flutter: как сохранять и восстанавливать состояние после перезапуска.
— Использование Restorable Routes для автоматического возвращения на нужный экран.
❗️Этот вебинар — отличная тренировка перед стартом курса «Flutter Mobile Developer» от OTUS.
👉 Записаться на вебинар → https://vk.cc/cNLk8U
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Избегайте использования lambda в конструкторе data-класса в Kotlin
В своих предыдущих статьях я показывал, почему использование
Эти проблемы в основном связаны с тем, как работают методы
https://proandroiddev.com/avoid-using-lambda-in-the-data-class-constructor-in-kotlin-a7d952de25c9
✍️ @kotlin_lib
В своих предыдущих статьях я показывал, почему использование
var
или Array
в конструкторе data-класса Kotlin приводит к неожиданному поведению и трудноуловимым багам.Эти проблемы в основном связаны с тем, как работают методы
equals()
, hashCode()
и copy()
— особенно при использовании в коллекциях вроде HashMap
, HashSet
, или в UI-фреймворках, таких как Jetpack Compose.https://proandroiddev.com/avoid-using-lambda-in-the-data-class-constructor-in-kotlin-a7d952de25c9
✍️ @kotlin_lib
👍2
Media is too big
VIEW IN TELEGRAM
Kotlin Coroutines — Обзор инструментов отладки
Корутины создают новые сложности при отладке — обычные трассировки стека мало помогают, когда асинхронная работа была запущена кодом, выполнявшимся в другом потоке. Это видео — короткий обзор нескольких инструментов для отладки корутин, которые вы могли упустить в IntelliJ IDEA и Android Studio.
источник
✍️ @kotlin_lib
Корутины создают новые сложности при отладке — обычные трассировки стека мало помогают, когда асинхронная работа была запущена кодом, выполнявшимся в другом потоке. Это видео — короткий обзор нескольких инструментов для отладки корутин, которые вы могли упустить в IntelliJ IDEA и Android Studio.
источник
✍️ @kotlin_lib
👍1