← Назад к вопросам
Для чего нужен noinline?
2.0 Middle🔥 21 комментариев
#Kotlin основы#Производительность и оптимизация
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Назначение noinline в Kotlin
noinline — это модификатор для параметров функций высшего порядка, который ЗАПРЕЩАЕТ компилятору Kotlin встраивать (inline) лямбду в код вызывающей функции.
Что такое inline?
По умолчанию функции с параметром-лямбдой пишутся с inline для оптимизации:
// По умолчанию: лямбда встраивается в код вызывающей функции
inline fun forEach(action: (Int) -> Unit) {
for (i in 1..3) {
action(i)
}
}
// Использование
forEach { i -> println(i) }
// После inlining (то, что делает компилятор):
for (i in 1..3) {
println(i)
}
Что делает noinline?
noinline отменяет встраивание для конкретного параметра:
inline fun myFunction(
inlineParam: (Int) -> Unit, // Будет встроена
noinline noInlineParam: (Int) -> Unit // НЕ будет встроена
) {
inlineParam(1) // Встраивается (нет вызова функции)
noInlineParam(2) // Обычный вызов функции
}
Зачем нужен noinline?
1. Сохранение лямбды в переменную
Без noinline компилятор не позволит сохранить лямбду, потому что она встраивается:
// ❌ Ошибка (inline не может быть сохранена)
inline fun saveCallback(callback: (Int) -> Unit) {
val stored = callback // IllegalStateException!
}
// ✅ Правильно с noinline
inline fun saveCallback(noinline callback: (Int) -> Unit) {
val stored = callback // OK
stored.invoke(42)
}
2. Передача лямбды дальше (как параметр)
// ❌ Inline нельзя передавать
inline fun processAndPass(action: (Int) -> Unit) {
processInThread(action) // Ошибка!
}
// ✅ С noinline работает
inline fun processAndPass(noinline action: (Int) -> Unit) {
processInThread(action) // OK
}
fun processInThread(action: (Int) -> Unit) {
Thread { action(42) }.start()
}
3. Сохранение в коллекции
// ❌ Inline нельзя в список
inline fun registerHandlers(handler: (String) -> Unit) {
val list = mutableListOf<(String) -> Unit>()
list.add(handler) // Ошибка!
}
// ✅ С noinline работает
inline fun registerHandlers(noinline handler: (String) -> Unit) {
val list = mutableListOf<(String) -> Unit>()
list.add(handler) // OK
}
Производительность: inline vs noinline
| Параметр | inline | noinline |
|---|---|---|
| Размер кода | Увеличивается | Нормальный |
| Скорость | Быстрее | Медленнее (вызов функции) |
| Возможность сохранить | ❌ Нет | ✅ Да |
| Когда использовать | Часто вызываемые | Редко вызываемые |
Практический пример
class EventBus {
private val listeners = mutableListOf<(Event) -> Unit>()
// ✅ Правильно: используем noinline для сохранения
fun subscribe(noinline listener: (Event) -> Unit) {
listeners.add(listener)
}
// ❌ Неправильно: inline не сможет сохраниться
// fun subscribe(listener: (Event) -> Unit) { ... }
fun emit(event: Event) {
// ✅ Здесь можно использовать inline
listeners.forEach { listener -> listener(event) }
}
}
class MyActivity {
fun onCreate() {
val bus = EventBus()
// Лямбда сохраняется, поэтому нужен noinline
bus.subscribe { event ->
println("Получено: $event")
}
}
}
Ещё примеры использования
Функция со смешанными параметрами:
inline fun retryOnFailure(
times: Int,
block: (Int) -> Unit, // inline (встроится)
noinline onError: (Exception) -> Unit // noinline (передаётся дальше)
) {
repeat(times) { attempt ->
try {
block(attempt) // Встраивается, быстро
} catch (e: Exception) {
onError(e) // Обычный вызов
}
}
}
crossinline для вложенных корутин:
inline fun runAsync(
crossinline block: suspend () -> Unit
) {
GlobalScope.launch {
block() // Используется в suspend функции
}
}
Итог
noinline нужен когда:
- Нужно сохранить лямбду в переменную
- Передать лямбду в другую функцию
- Сохранить лямбду в коллекции
- Лямбда используется в контексте, где inline невозможен
Без noinline:
- Компилятор встраивает лямбду для оптимизации
- Код работает быстрее, но зато увеличивается размер
- Лямбду нельзя сохранить