Kas*_*ala 0 lambda android inline kotlin
我将我的function有lambda作为parameter到inline function性能改进.
我list的lambda类型的MutableList<(Authenticate) -> Unit>变量作为类数据成员.当我尝试添加lambda parameter到list.
Kotlin编译器说:
非法使用内联参数回调
这是代码
// Some code skipped
object Odoo {
val pendingAuthenticateCallbacks = mutableListOf<(Authenticate) -> Unit>()
inline fun authenticate(
login: String, password: String, database: String,
quick: Boolean = false, crossinline callback: Authenticate.() -> Unit
) {
// Following statement has error saying
// Illegal usage of inline parameter callback. add 'noinline' modifier to parameter declaration.
pendingAuthenticateCallbacks += callback
// Error in above statement
if (pendingAuthenticateCallbacks.size == 1) {
// Retrofit2 Object boxing code skipped
val call = request.authenticate(requestBody)
call.enqueue(object : Callback<Authenticate> {
override fun onFailure(call: Call<Authenticate>, t: Throwable) {
(pendingAuthenticateCallbacks.size - 1 downTo 0)
.map { pendingAuthenticateCallbacks.removeAt(it) }
.forEach {
it(Authenticate(httpError = HttpError(
Int.MAX_VALUE,
t.message!!
)))
}
}
override fun onResponse(call: Call<Authenticate>, response: Response<Authenticate>) {
(pendingAuthenticateCallbacks.size - 1 downTo 0)
.map { pendingAuthenticateCallbacks.removeAt(it) }
.forEach {
it(Authenticate(httpError = HttpError(
response.code(),
response.errorBody()!!.string()
)))
}
}
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
内联将lambda中的代码直接插入到调用站点中,这消除了拥有函数对象的开销.
例如,这大致导致main:
fun withLambda(lambda: () -> Unit) {
lambda()
}
inline fun inlinedLambda(lambda: () -> Unit) {
lambda()
}
fun main(args: Array<String>) {
withLambda { println("Hello, world") }
inlinedLambda { println("Hello, world") }
}
Run Code Online (Sandbox Code Playgroud)
被转换为:
fun main(args: Array<String>) {
withLambda { println("Hello, world") }
println("Hello, world") // <- Directly inserted!
}
Run Code Online (Sandbox Code Playgroud)
如果你有
pendingAuthenticateCallbacks += callback
Run Code Online (Sandbox Code Playgroud)
这是不可能的,因为callback必须是一个对象才能将它添加到列表中.
您需要添加noinline修饰符.
粗略的近似是指内联lambda不能被视为一个对象,因为它并不真正作为一个对象存在.它直接使用而不是作为对象创建.
当然,你可以创建一个包含lambda:
pendingAuthenticateCallbacks += { callback() } // Not a good idea
Run Code Online (Sandbox Code Playgroud)
但这完全打败了内联点(不要这样做!).
但是,创建参数noinline意味着您的方法现在具有可以内联的零lambda参数,因此您也可以删除inline修饰符,因为性能优势最小.
编译器应该认识到这一点:
请注意,如果内联函数没有可嵌入的函数参数且没有具体的类型参数,编译器将发出警告,因为内联此类函数不太可能有益.
内联方法的主要原因是使用lambda和reified泛型类型参数时的性能.作为科特林1.1的,但也可以具有用于属性内嵌属性访问而不支持字段.
简而言之,如果您没有lambda参数(或者没有reified类型参数,在这种情况下您必须),将函数标记为无意义通常是没有意义的inline.
| 归档时间: |
|
| 查看次数: |
503 次 |
| 最近记录: |