從forEach理解一下kotlin的inline

山有木xi發表於2024-02-26

Android 開發中有很多語法糖 其中 for Each 可以替代 for 迴圈 ,簡潔 的語法是很常用的

tempList.forEach {
   Timber.d("print list value =>${it}")
}

在使用 for Each 相信每個開發者都會踩的一個坑就是 for Each 中的 return@forEach 無法直接退出 forEach

tempList.forEach {
   if (it == ""){
       return@forEach
   }
   Timber.d("print list value =>${it}")
}

先說個最常見的解決方案 在外層包一個 run 然後使用 return@run 退出即可

run{
   tempList.forEach {
       if (it == ""){
           return@run
       }
       Timber.d("print list value =>${it}")
   }
}

那麼為什麼 for Each 不能直接退出呢 這就要從 kotlin 中有個非常好用的關鍵字 inline 說起 它可以幫你對做了標記的函式進行內聯最佳化。所謂內聯就是,呼叫的函式在編譯的時候會變成程式碼內嵌的形式

fun test(){
   testInline()
}
private inline fun testInline(){
   Timber.d("testInline")
}
//等於
fun test(){
   Timber.d("testInline")
}

kotlin 中方法也是變數 所以這樣做的區別在於 不實用 inline 每次呼叫會多建立一個變數 在頻繁的呼叫時 例如 for 迴圈中 記憶體的開銷會變得很大

這也解釋了 for Each 為什麼要使用 inline

如果針對其中某個引數不需要 inline 可以使用 no Inline 效果如下

inline fun test1(first:()->Unit,noinline second:()->Unit){
   first()
   Timber.d("3")
   second()
}
fun main(){
   test1({
         Timber.d("1")
   },{
       Timber.d("2")
   })
}

等於

fun main(){
   Timber.d("1")
   Timber.d("3")
   ({
       Timber.d("2")
   })
}

這裡面有個坑 我們前面提到 kotlin 中方法也是變數 所以在實際使用中 就可以加上 noInline 來返回該方法

inline fun test1(first:()->Unit, noinline second:()->Unit): () -> Unit {
   first()
   Timber.d("3")
   return second
}

如果不加上 no Inlie

這是因為這時實際編譯結果是

fun main(){
   Timber.d("1")
   Timber.d("3")
   Timber.d("2")
   second
}

可以看到最後突兀的出現一個 second

除了 no Inline 還有個 crossInline 剛才講的 noinline 是區域性關閉內聯最佳化 而這個 crossinline ,是區域性加強內聯最佳化

再看一下例子

inline fun test1(first:()->Unit) {
   first()
   Timber.d("2")
}
fun main(){
   test1{
       Timber.d("1")
       return
   }
}

當我在使用行內函數時在裡面呼叫了 return 因為使用內聯 方法到最後是展開的 也就是

fun main(){
   Timber.d("1")
   Timber.d("2")
   return
}

所以 他的本質是結束 mai n 函式 而不是隻結束 test 1 函式

如果將 test 1 first 的呼叫放在主執行緒中

可以看到系統提示要使用 cross Inline 在使用之後 就會告訴不允許在 mai n 當中這樣使用 main 當中只能 return @ test 1

所以什麼時候需要 crossinline?當你需要突破行內函數的「不能間接呼叫引數」的限制的時候。


來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/69917874/viewspace-3007312/,如需轉載,請註明出處,否則將追究法律責任。

相關文章