Мобильное Чтиво
1.6K subscribers
271 photos
43 videos
153 links
Очень серьезный канал про мобильную разработку. Веду канал я — @maxkachinkin
Download Telegram
🎤 Увидимся на конференциях!

Так вышло, что конец года у меня получился очень насыщенным по конференциям 😅

Как так получилось? Летом я решил: подамся в разные конфы, если куда-то возьмут — круто!
В прошлом году, например, DevFest Istanbul мне отказал, DroidCon — тоже в разное время отказывал.

А в этом году апрувнули пять ивентов. Ну и я такой, а чё бы и нет — поеду на все! 🚀

И даже Droidcon для меня наконец-то разблокировался.
Да, не Лондон и не Нью-Йорк, а Абу-Даби, но для старта — шикарно.
Тем более можно будет потусить в Drinkit в Дубае

Вот мой декабрьский маршрут:
🇹🇷 6 Dec — DevFest Mersin
🇹🇷 7 Dec — DevFest Istanbul
🇹🇷 13 Dec — DevFest Izmir
🇦🇪 15 Dec — Droidcon Abu Dhabi
🇦🇲 20 Dec — DevFest Armenia

Если кто из вас живёт или работает в этих городах — пишите, приходите на конфу!
Поговорим про Android, Compose, AI, ну и просто пообщаемся.
Будет весело 🔥

#android #conference #devfest #droidcon
1🔥275👏3🤡2💩1
🧙‍♂️ Не люблю магию… или что такое SPI в Android

Подключаю в Gradle:

implementation "com.google.firebase:firebase-ai"


Всё билдится. Запускаю. И… краш:

ch.qos.logback.classic.Logger cannot be found

Что?? 😳 Я просто подключил Firebase AI, а мой логгер куда-то испарился.

Я разобрался в чем может быть такой приступ магии. И вам сейчас расскажу. Начну изделака.

⚙️ Про SPI (Service Provider Interface)
SPI — это такой механизм динамической подстановки реализаций в рантайме.
Java смотрит в папку META-INF/services/ и подгружает первую попавшуюся реализацию интерфейса.
Например, ILoggerFactory может быть реализован в Logback, а может в другом логгере.

По сути плагин-система: API одно, реализаций может быть несколько.
И вот тут начинается магия… 🧙‍♀️

💥 Почему всё сломалось
SLF4J (фасад для логгирования) как раз использует SPI.
Ты используешь Logback и всё работает.
Но Firebase AI приносит с собой slf4j-nop (!!!) реализацию, которая делает ничего.

В результате:
- на classpath теперь две реализации: Logback и NOP;
- SPI выбирает первую попавшуюся;
- и… ClassCastException, если ты ожидал Logback. А я ожидаю именно Logback (у нас там своя заморочка с ним)

🧠 Как работает SPI внутри
Когда приложение стартует:
- JVM сканирует META-INF/services/...
- Находит все реализации SLF4JServiceProvider
- И уже конкретная библиотека (SLF4J) берёт первую и всё!

Вот почему оно билдится, но падает в рантайме — SPI выбирает не то, что я думал.

💡 Почему SPI не зло в общем случае
SPI — это способ разрабатывать интерфейс и реализации независимо. Интерфейс подулючаешь отдельной либой, реализацию отдельной. Потом можешь менять.

Но есть и минус:
🔴 если на classpath два провайдера, то побеждает случайность.

💬 А вы вообще знали, что такое SPI? Любите магию рантайма или предпочитаете явное ручной контроль? 🔧

#android #kotlin #spi #slf4j #firebase #logging
🔥85👍4
60% кода за меня пишет AI

Так говорит Dashboard в Cursor, которым я пользуюсь наиболее активно последнее время.

Если честно, мне сложно оценить на сколько это правда или нет 🤔 — как именно он считает, что учитывает и т.д.

На текущем этапе своего AI-развития, я не очень верю, что всегда и везде должно быть 100%. Сильно зависит от специфики задач и проекта. Какие-то фичи и проекты, наверное, можно написать 99% через AI. А какие-то — и на 10% я бы пока не дал.

Но по внутреннему ощущению, для большинства фич для среднестатистического разработчика среднестатистического мобильного приложения что-то около 90% вполне себе может быть. Согласны? Или больше? 😏

Я буду делиться своими инсайтами того, как я именно пользуюсь.
💬 А пока хочется узнать у вас — чем вы сейчас пользуетесь?

Прошло какое-то время, и супер-мега хайп успокоился, и, наверное, все выбрали себе тот или иной инструмент. Какой у вас?
Я запущу голосовалку следующим постом 📊
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍2💩2🤡21
Please open Telegram to view this post
VIEW IN TELEGRAM
🤡5🥱2💅21
🧠 TDD с AI: норм или стрем?

Сегодня я к вам с размышлением и небольшим тестом.

Есть такая классная инженерная практика — TDD.
Мне кажется, нет ни одного человека, который бы спорил с тем, что в теории она крутая.
Но на практике многие разработчики её не любят — она контринтуитивна, требует дисциплины, кажется, что это трата времени, и вообще… лень 😅

Но раз теперь с нами AI — то слово «лень» должно потихоньку уходить из словаря. И я задумался: насколько вообще TDD хорошо сочетается с работой с AI-агентами?

TL;DR: TDD с платными AI — слишком дорого. TDD с локальными LLM и агентами — 🔥

🔁 TDD работает малыми циклами. А циклы против токенов. Вообще, чем больше циклов — тем больше токенов.

Для нас, людей, короткие итерации — кайф.
Но для AI — это жесть в смысле контекста. Каждый микрошаг — новый запрос, новый контекст, новые токены.

📊 Я сделал тест “на коленке” (до реального проекта пока не дошли руки).
Сравнил TDD и Tests-first:
• TDD: 20 циклов “тест–фикс”, примерно 800k входных и 300k выходных токенов.
• Tests-first: 1 спека + тесты + 2 маленьких фикса → 300k входных и 120k выходных токенов.

Если взять цены OpenAI с моделью GPT-5, то выходит примерно:
💸 TDD ≈ $4.00
💸 Tests-first ≈ $1.58

Да, здесь куча допущений и неоптимальностей:
- возможно, нужен отдельный TDD-агент, который будет экономно итерироваться, и я просто неправильно делал TDD c AI;
- возможно, не нужна такая дорогая модель;
- да и вообще неправильно так считать, потому что бОльшая часть токенов будет кэшироваться, и реальная цена — сильно ниже.

Но anyway я почти уверен, что при платных токенах TDD всё равно выйдет дороже, чем Tests-first. Ну т.е. дороже на столько, что оно потеряет смысл. Слишком много итераций туда-сюда.

А вот если LLM локальная, своя, и вы не платите за каждый токен — тогда, я думаю, TDD с AI самое то! 🚀

Остаётся вопрос, как это поведёт себя на больших проектах. Помимо токенов, важно ещё, как модель держит контекст.

📍Мой личный промежуточный вывод:
TDD с платными AI — слишком дорого.
TDD с локальными LLM и агентами — круто.


💬 А что вы думаете? Мне реально очень интересно! Может, я не прав и что-то не учел?
Может, кто-то уже использует спец-агента под TDD, и у него всё прекрасно? Расскажите!

#AI #TDD #engineering
👍7😁31🥴1
AI становится новой мультиплатформой? 🤔⚡️

Недавно смотрел доклад Kevin Galligan How AI Will Change Mobile Development. Того самого чела, кто годами топит за KMP на Droidcon, KotlinConf и вообще везде.

И в этом докладе он формулирует мысль, которая меня прям зацепила:
наш новый KMP — это AI.

AIMP — AI Multiplatform (это уже я сам придумал 😅).

Идея простая:
- вместо ещё одного кроссплатформенного фреймворка у нас появляется слой из AI-агентов и тулов
- они позволяют нативным командам работать эффективнее, как будто это “кроссплатформа”
- легко переносить фичи между платформами, меньше дублировать логику, быстрее разбираться в чужом стеке.
- зачем нужен кроссплатформенный фреймворк, если c AI мы сами можем стать кроссплатформенными?

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

Я, честно, сам ещё далеко “не там”.
Но всё чаще ловлю моменты, когда:
- лезу в менее знакомый iOS-код, и быстрее разбираюсь с AI
- или говорю агенту: «смотри, как это сделано на iOS, помоги повторить на Android»

AI уже начал делать меня чуть более “кроссплатформенным” разработчиком, хотя я по-прежнему глубоко знаю только Android.

И вот вопрос к вам 👇
- Для вас AI уже начинает играть роль замены классической кроссплатформы?
- Чувствуете, что стали смелее смотреть на другую платформу — или пока держитесь в своём лагере?
- Не кажется ли вам, что вместо “KMP vs Flutter vs Swift на Android” нас ждёт эпоха, где AI просто делает нас всех кроссплатформенными?

#ai #kmp #aimp #crossplatform #androiddev #iosdev
🤔11💩11🔥4🤮3💯32👍2
🎨 Стартую мини-серию постов про шейдеры

Друзья, давно хотел сделать что-то не про AI, и вот — наконец-то.
Запускаю маленькую серию постов про шейдеры на Android.

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

Сегодня — разогрев. Прям базовая база.

Большинство наших UI-фич — это верстка, анимации, стейты. Но под этим всем есть GPU. Его архитектура такая, что он может параллально обрабатывать сразу с кучей пикселей! И обрабатывает он их по программе, которую называют фрагментный шейдер, или просто шейдер.

Грубо говоря, шейдер — это функция, которая для каждого пикселя считает цвет. И GPU запускает её параллельно на всех пикселях!

AGSL + RenderEffect
С Android 13 появился AGSL — Android-вариант GLSL, но встроенный прямо в рендеринг UI.

Почему это круто:
- OpenGL это много кода! Надо создавать контекст, вершины и кучу всего
- просто пишешь строку с шейдером
- создаёшь RuntimeShader
- навешиваешь RenderEffect на View или graphicsLayer в Compose
- и всё!

Можете попросить AI написать вам 2 варианта шейдера через AGSL и GLSL — и поймете, почему AGSL так крут. Он просто экономит нам кучу (реально кучу) бойлерплейт кода.

Чтобы начать с базы, рассмотрим простой пример: красный фильтр за 3 строки


uniform shader image

Это входная картинка.
image — это ваш Composable/View, уже нарисованный Android’ом.


uniform float intensity;

Это внешний аргумент, мы им управляем через setFloatUniform

main — главная функция шейдера. Она вызывается для каждого пикселя.


half4 color = image.eval(coord);

Берём оригинальный цвет пикселя.


half4 red = half4(1.0, 0.0, 0.0, 1.0);

Создаём вектор для чистого красного цвета.


float t = clamp(intensity, 0.0, 1.0);

clamp это как coerceIn()


mix(a, b, t)

Линейная интерполяция между цветами — возвращаем цвет пикселя, частично смешанный с красным

И всё — результат прикрепил. Добавил анимацию значения intensity, чтобы видно было как работает передача аргументов.

💬
Расскажите, на сколько вы работали с шейдерами?
И на сколько вам интересна эта тема, чтобы я продолжил показывать разные практические примеры?

#android #ui #shader
🔥286👍5💩1
🌈 Шейдеры, часть 2. Делаем живой градиент

Продолжаю свою мини-серию про шейдеры.
В прошлый раз мы разбирались с mix(), сегодня пойдём дальше.

Градиент — это вещь, которую должен уметь каждый.

Я накидал простой пример (видите на видео), буду рассказывать на нем.

Как передавать параметры уже рассказывать не буду. Но в этом примере покажу, что в Compose у нас есть ShaderBrush. Это означает, что любой шейдер можно превратить в кисточку. И всё, что умеет рисовать Compose (drawRect, drawPath, drawCircle, текст, рамки) —
может быть нарисовано по правилам шейдера!

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


vec2 uv = fragCoord / resolution;


Мы делим координаты пикселя на размер экрана — получаем uv в диапазоне 0..1


float wave = sin(time * 0.8 + uv.x * 4.0);


Тут получаем ту самую волну от -1 до 1, со скоростью 0.8 и шириной 4.0 (сколько волн поместится по ширине).


float t = 0.5 + 0.5 * wave;


Так мы переводим синус в удобный диапазон

return mix(color1, color2, t);


А это уже известная нам функция линейной интерполяции. Грубо говоря:
- t = 0 → цвет = color1
- t = 1 → цвет = color2

Вот и всё!
Теперь у нас градиент, который:
- горизонтально переливается из одного цвета в другой
- и одновременно движется благодаря синусу и времени

easy-peasy

#android #compose #ui #shaders #agsl #graphics #gradient
🔥21👍7💩2🥴1😍1
This media is not supported in your browser
VIEW IN TELEGRAM
🚨Code red! I repeat, CODE RED!! 🚨

Что-то очень странное сегодня происходит с приложением Drinkit.
1🔥457🤔2😱2👾1
🔥 Live Updates в Dodo

Google на I/O представили новую фичу для Android — Live Updates.

Мы не могли пройти мимо 😅
Завезли и в Dodo Pizza и в Drinkit!

Серёга Орлов недавно сделал подробную статью — как мы прикрутили Live Updates в Dodo Pizza 🚚🍕

Всё уже в проде, и пользователи это реально видят, доставка теперь ощущается живее.

В Drinkit 💙 мы тоже сделали Live Updates. И там получился свой прикольный кейс.
Про него бахну пост завтра 😉

#android #liveupdates #dodopizza #drinkit
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍4
🐋🔔 Live Updates в Drinkit!

Мы в Drinkit затащили Live Updates на Android! Мне очень нравится, как это выглядит, прям кайф!

Фичу делал Гриша Шимичев. Он год назад сделал наш "Live Activity" на Android (красивый rich notification, похожий на Live Activity на iOS). Теперь же, когда Google выкатил официальную штуку, затащил и её 😎

Кто не знает, что крутого в Live Updates:
- аккуратный chip в статус-баре
- прогресс-бар прямо в уведомлении
- поддержка Always-on Display

Мы добавили красоты: разных милых пиксельных зверят под разные статусы заказа 🐰🦊🐼

Если у вас Android 16+, приложение включает Live Updates.
Если ниже — будет наш старый красивый кастомный вариант.

Мне очень нравится, как всё получилось. И по внешнему виду, и по вниманию к нюансам.

Еще, у нас там интересный микс из пушей и ForegroundService для обновления статуса, но об этом расскажу как-нибудь позже 😉

💬 Как вам Live Updates? Вообще видите ли в нем ценность?

#android #notifications #drinkit #liveupdates
🔥21👍6🤮2💩1🦄1
🟢 Android Developers тоже ожидает доклад Ordering Coffee with Firebase AI

Предполагаю, что большинство читаталей канала живут в других городах. Но!

Если вы из Mersin, Istanbul, Izmir, Abu Dhabi (или Dubai) или Yerevan — приходите на конфу! Пообщаемся, затусим! 🥳

Буду здесь:
🇹🇷 6 Dec — DevFest Mersin
🇹🇷 7 Dec — DevFest Istanbul
🇹🇷 13 Dec — DevFest Izmir
🇦🇪 15 Dec — Droidcon Abu Dhabi
🇦🇲 20 Dec — DevFest Yerevan

#devfest #droidcon #conference
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥334👍3👎1
This media is not supported in your browser
VIEW IN TELEGRAM
18🤣7👍5💩3
Шейдеры, часть 3. Начинаем делать Glitch

Продолжаю мини-серию про шейдеры.
В прошлый раз мы делали живой градиент, сегодня начну подходить к теме Glitch — как сделать первый эффект из Upside-Down фичи.

Glitch строится на искажении картинки. И самое это волна.

Поэтому сделаем два маленьких примера.

1. Статическая волна

float wave = sin(uv.y * 40.0);
float amplitude = 0.01 * intensity;
uv.x += wave * amplitude;


Что тут происходит:
- берём uv.y, вертикальную координату (номер строки пикселя)
- умножаем на 40, чтобы получить плотную волну
- пропускаем через sin(), получаем значение от -1 до 1
- сдвигаем пиксели по X пропорционально этой волне

В результате есть волна, но она стоит.

2. Анимированная волна

float wave = sin(uv.y * 40.0 + time * 5.0);

Здесь уже волна плывет. Вот почему:

- time * 5.0 это скорость движения волны
- синус теперь зависит не только от uv.y, но и от того, сколько времени прошло
- поэтому картинка начинает течь горизонтально

Это уже ближе к глитчу! В будущих постах буду дальше идти и дойдем до глитча!

#android #ui #compose #shaders #agsl #graphics #glitch
👍13🔥7🖕3💩2🤡2