Comments 10
Спасибо за статью и подробное объяснение!
Добавлю небольшое уточнение по поводу crossinline
.
private inline fun crossInlineFun(crossinline body: () -> String) {
val func = {
"crossInline func code, " + body.invoke()
}
regularFun(func)
}
В этом примере нужен crossinline
, так как в передаваемой лямбде-параметре body
на стороне вызывающей функции могут быть non-local returns, и поэтому body
нельзя передавать в другой контекст исполнения (в лямбду func
). Чтобы исправить это, можно либо отменить инлайнинг body
(добавив noinline
), либо запретив использовать non-local returns внутри body
(добавив crossinline
). В этом примере более предпочтителен вариант с crossinline
, так как он позволяет всё-таки заинлайнить body
.
noinline
же полезен в том случае, когда, например, нужно работать с лямбдой-параметром в inline функции как с обычной переменной или передать в качестве параметра в "не inline" функцию.
private inline fun crossInlineFun(noinline body: () -> String) {
val someFunc = body
regularFun(func)
}
Здесь отменяется илнайнинг body
, поэтому для него создаётся инстанс анонимного класса, и с ним можно работать как с обычной переменной.
Этот пример очень хорошо показывает, что inline функции никак не помогают нам экономить количество методов.
Это неправда. Помогают, если включена минификация. Если инлайн-метод не используется из джавы, то он будет вырезан.
Не надо пытаться помогать JIT компилятору делать его работу)
Суть инлайнинга не в экономии методов. Косвенно он может их сокращать, но задуман он совсем не для этого.
Это никак не противоречит тому, что я сказал. Утверждение в статье от этого правдой не становится.
Вот честно, тезис о том, что inline экономит количество методов, только от вас услышал. Обычно говорят, что он уменьшает количество вызовов, что может быть хорошо в циклах.
Лямбда аргументы inline функции прозрачны для контекстов suspend
и @Composable
suspend fun test() = Unit
fun repeat1(i: Int, action: (Int) -> Unit): Unit = TODO()
suspend fun context() {
repeat1(5) {
test()
}
}
Такой код с repeat без inline не скомпилируется, нужно чтобы было action: suspend (Int) -> Unit
. А потом появляется Compose и нужна +1 перегрузка. С inline одна декларация работает сразу с любыми вызовами
Kotlin под капотом: inline функции