Промты для Kotlin-корутин и Flow: как LLM закрывает утечки памяти и гонки данных в проде

LLM уже неплохо справляются с Kotlin, но качество ответа сильно зависит от формулировки промта. Если попросить «напиши ViewModel с корутинами», можно получить код, который компилируется, но течёт по памяти или теряет состояние при повороте экрана. Другое дело — точный промт с указанием контекста, ограничений и ожидаемого результата.

В этой подборке — 12 промтов для Kotlin и Jetpack Compose. Одни заточены под асинхронную логику и работу с данными (корутины, Flow, ViewModel), другие — под вёрстку и состояние экрана (Compose). Критерий выбора простой: если задача про то, как получить и обработать данные, берите промты из первой группы; если про то, как показать и обновить UI, — из второй. Каждый промт сопровождается примером использования и фрагментом кода.

Как работать с этими промтами

LLM не знает ваш проект. Чем больше контекста вы дадите — версия Kotlin, используемые библиотеки (Hilt, Retrofit, Room), архитектурный паттерн, — тем меньше придётся переписывать. В каждом промте ниже есть плейсхолдеры в фигурных скобках: замените их на свои значения.

Ключевое различие Промты для корутин и Flow требуют явного указания диспетчера, области видимости и обработки ошибок. Промты для Compose — явного указания состояния, рекомпозиции и жизненного цикла. Смешивать их в одном запросе почти всегда плохо: LLM начинает путать ответственность слоёв.

Ниже — проверенные формулировки. Для удобства они сгруппированы по назначению.

Промты для корутин и Flow

1. Безопасный запуск корутин в ViewModel

Задача: получить корутину, которая не переживёт ViewModel и не утечёт при отмене.

Промт:

Ты — Android-разработчик. Напиши ViewModel на Kotlin с использованием kotlinx.coroutines. 
Требования:
- используй viewModelScope для всех корутин;
- при запуске suspend-функции {название} обрабатывай CancellationException и не глотай его;
- добавь обработку исключений через CoroutineExceptionHandler или try/catch с логированием;
- покажи, как отменить корутину при очистке ViewModel.
Версия Kotlin: 2.0. Библиотека: kotlinx-coroutines-android 1.8.0.

Пример использования: вы пишете ViewModel для загрузки профиля. LLM сгенерирует метод loadProfile(), который запускается в viewModelScope.launch, оборачивает вызов в try/catch, а в onCleared() (или через viewModelScope) автоматически отменяет корутину. Без этого промта модель часто предлагает GlobalScope.launch — прямой путь к утечке.

2. Холодный Flow с правильной буферизацией

Задача: получить Flow, который не блокирует эмиссию и корректно работает с медленным коллектором.

Промт:

Создай cold Flow на Kotlin, который эмитит значения из {источник, например, Room или сеть}. 
Условия:
- используй flow { } или channelFlow { };
- добавь оператор buffer() с ёмкостью {N} и объясни, зачем он нужен;
- покажи, как коллектор может отписаться без утечки;
- приведи пример с collectLatest и объясни разницу с collect.

Пример: для потока обновлений курса валют из сети channelFlow с buffer(10) позволит не терять промежуточные значения, если UI обрабатывает их медленнее. LLM также покажет, что collectLatest отменяет предыдущую обработку — это критично для поиска с задержкой.

3. Обработка ошибок в корутинах без потери состояния

Задача: не дать исключению убить всю цепочку и сохранить предыдущие данные.

Промт:

Напиши suspend-функцию {название}, которая делает сетевой запрос и возвращает Result<{тип}>. 
Требования:
- используй runCatching или try/catch, но не подавляй CancellationException;
- при ошибке сети верни Result.failure с кастомным исключением;
- покажи, как во ViewModel обновить UI-состояние ошибкой, не сбрасывая уже загруженные данные.

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

4. Тестирование корутин с TestDispatcher

Задача: получить рабочий unit-тест для suspend-функции без реальных задержек.

Промт:

Напиши unit-тест на JUnit5 для suspend-функции {название}, используя kotlinx-coroutines-test. 
Условия:
- замени главный диспетчер на StandardTestDispatcher;
- используй runTest и advanceUntilIdle;
- проверь, что при ошибке возвращается корректный Result;
- покажи, как избежать утечки тестового диспетчера между тестами.

Пример: тест для loadProfile() с эмуляцией задержки 100 мс выполнится мгновенно, а advanceUntilIdle() гарантирует, что все корутины завершились до проверки.

Промты для ViewModel и состояния

5. ViewModel с MutableStateFlow и неизменяемым состоянием

Задача: получить предсказуемый UI-стейт, который не меняется вручную из UI.

Промт:

Создай ViewModel для экрана {название}. 
Требования:
- используй MutableStateFlow<{UiState}> с приватным сеттером и публичным StateFlow;
- UiState — data class с полями {перечислить};
- все обновления состояния — только через методы ViewModel;
- покажи, как собрать состояние из нескольких Flow через combine.

Пример: для экрана корзины UiState содержит список товаров, общую сумму и флаг загрузки. LLM сгенерирует private val _uiState = MutableStateFlow(CartUiState()) и val uiState = _uiState.asStateFlow(), исключив прямую мутацию из Composable.

6. Обработка однократных событий (навигация, тосты)

Задача: не показывать тост повторно при рекомпозиции.

Промт:

Реализуй во ViewModel механизм однократных событий для {навигация / показ тоста}. 
Варианты: Channel, SharedFlow с replay=0, или StateFlow с ручным сбросом. 
Сравни их по надёжности и выбери лучший для {сценарий}. 
Покажи, как Composable подписывается на события через LaunchedEffect без дублирования.

Пример: LLM порекомендует Channel с receiveAsFlow() для навигации, так как SharedFlow без replay может потерять событие при подписке после рекомпозиции. В примере кода будет LaunchedEffect(Unit) { viewModel.events.collect { ... } }.

7. Инъекция зависимостей во ViewModel через Hilt

Задача: получить ViewModel с репозиторием, внедрённым через конструктор, без ручного создания фабрик.

Промт:

Покажи, как объявить ViewModel с @HiltViewModel и внедрить в неё репозиторий через конструктор. 
Добавь аннотации @Inject и объясни, почему не нужен ViewModelProvider.Factory. 
Приведи пример модуля Hilt для предоставления репозитория.

Пример: LLM сгенерирует @HiltViewModel class MyViewModel @Inject constructor(private val repo: MyRepository) : ViewModel(), а также модуль с @Provides fun provideRepo(...). Это избавит от boilerplate с фабриками.

Промты для Jetpack Compose

8. Stateless-компонент с hoisting состояния

Задача: разделить UI и логику, чтобы Composable легко тестировать.

Промт:

Напиши Composable {название} для отображения {что}. 
Сделай его stateless: все состояние и колбэки передавай через параметры. 
Покажи два варианта: stateless и stateful-обёртку, которая подписывается на ViewModel. 
Объясни, почему hoisting состояния улучшает переиспользование и тестируемость.

Пример: для списка задач LLM создаст TaskList(tasks: List<Task>, onTaskClick: (Task) -> Unit) и обёртку TaskListScreen(viewModel), которая передаёт viewModel.uiState.collectAsState(). Такой компонент можно проверить в Preview без ViewModel.

9. Оптимизация рекомпозиции в списках

Задача: избежать лишних перерисовок при изменении одного элемента.

Промт:

У меня есть LazyColumn с элементами {тип}. 
Предложи способы уменьшить рекомпозицию: key в items, derivedStateOf, remember с правильными ключами. 
Покажи антипаттерн, когда лямбда создаётся заново при каждой рекомпозиции, и как это исправить.

Пример: LLM укажет, что items(tasks, key = { it.id }) помогает Compose переиспользовать элементы, а remember(tasks) { ... } избежать пересчёта производного состояния. Также покажет, что передача onClick = { viewModel.onTaskClick(it) } без remember создаёт новую лямбду при каждой рекомпозиции — лучше использовать method reference или remember.

10. Безопасная работа с контекстом и ресурсами

Задача: не утекать Activity через Composable.

Промт:

Как в Composable получить строковый ресурс или контекст без утечки? 
Покажи правильный способ через stringResource и LocalContext, объясни, почему нельзя сохранять context в долгоживущих объектах. 
Приведи пример с remember для получения цвета из ресурсов.

Пример: LLM покажет val context = LocalContext.current и предупредит, что сохранять его в ViewModel или синглтоне нельзя — это утечка Activity. Для цветов посоветует colorResource(id = R.color.my_color).

11. Навигация с сохранением состояния

Задача: сохранить состояние экрана при переходе вперёд и назад.

Промт:

Реализуй навигацию в Compose с помощью NavHost. 
Покажи, как сохранить состояние скролла LazyColumn при возврате на экран. 
Используй rememberSaveable и объясни, чем он отличается от remember. 
Добавь пример с аргументами навигации и типами {тип аргумента}.

Пример: для списка товаров с переходом в детали LLM предложит обернуть LazyListState в rememberSaveable с кастомным Saver, чтобы позиция скролла восстанавливалась.

12. Тема и стили без дублирования

Задача: вынести цвета и типографику в единую тему.

Промт:

Создай MaterialTheme для приложения с кастомными цветами {перечислить} и типографикой. 
Покажи, как использовать её в Composable через MaterialTheme.colorScheme и MaterialTheme.typography. 
Добавь пример переключения светлой/тёмной темы через isSystemInDarkTheme.

Пример: LLM сгенерирует AppTheme с darkColorScheme и lightColorScheme, а также покажет, как в @Composable получить цвет через MaterialTheme.colorScheme.primary.

Сравнение групп промтов

Критерий Промты для корутин и Flow Промты для Compose
Фокус Асинхронность, потоки данных, ошибки UI, состояние, рекомпозиция
Ключевые слова в промте viewModelScope, Dispatchers, Flow, suspend, try/catch remember, LaunchedEffect, state hoisting, recomposition
Частая ошибка без промта GlobalScope, потеря CancellationException Состояние внутри Composable, утечка контекста
Что проверять в ответе Отмена корутин, обработка исключений Стабильность лямбд, ключи в списках
Что проверить первым В любом сгенерированном коде ищите GlobalScope и Dispatchers.Main без необходимости — это первые признаки потенциальной утечки. В Compose — изменяемое состояние вне remember и отсутствие key в items.

Итог

Промты — это не замена знаниям, а ускоритель. Чем точнее вы опишете контекст и ограничения, тем меньше времени потратите на правки. Для асинхронной логики всегда указывайте область видимости и обработку ошибок, для UI — состояние и жизненный цикл.

Попробуйте эти формулировки в своём проекте. Если хотите глубже разобраться в корутинах и Compose, обратите внимание на наши курсы по мобильной разработке — там разбираем не только синтаксис, но и подводные камни, которые LLM часто упускает.

← Все статьи

Спросить AI по этой статье

Задайте вопрос по этой статье — ASI Biont ответит, опираясь на её текст.

Читайте также

Нейрохакинг и когнитивная оптимизация: как за неделю собрать протокол, который реально работает

27 октября 2026

Компьютерные сети (CCNA): собираем WireGuard-сервер на VPS — практический гайд по VPN и сетевой безопасности

27 октября 2026

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

27 октября 2026

Юнит-тесты на Python с LLM: 12 промтов от pytest-фикстур до Hypothesis, которые закрывают непокрытые ветки

27 октября 2026

Расторжение договора с фитнес-клубом или салоном красоты и возврат денег: разбор условий, сроков и претензий в 2026 году

27 октября 2026

Full-Stack AI Engineer: как RAG-пайплайны, векторные базы данных и развертывание LLM на самом деле работают в продакшене

28 октября 2026

Сверка актов вручную или промптом: где LLM экономит бухгалтеру часы, а где создаёт риски

12 ноября 2026

Уголовное дело: защита и стратегия — как не сломать себе жизнь на первом допросе

28 октября 2026

Kotlin на максималках: 13 промтов, с которыми Android-разработка идёт быстрее рутины

29 октября 2026