iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
Mobile Development

新手向Android&Kotlin學習紀錄30天系列 第 25

第25天 Kotlin小學堂(14) : Lateinit & Lazy properties

  • 分享至 

  • xImage
  •  

昨天講到了可空類型,今天可以來了解一下延遲初始化,因為還蠻常使用到的

我們使用Android Studio開了專案,拉好UI元件後,需要在Activity類別中宣告這個物件的存在,兩者才會有關連,我們也才可以透過程式碼來控制元件,比如說按鈕的點擊事件。

如果我們不延遲初始化變數的話,會在MainActivity.kt這樣宣告TextView:

class MainActivity : AppCompatActivity() {
    //因為要一定要賦值給變數但是又還不能初始化,就會寫這樣
    private var textView : TextView? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //textView初始化
        textView = findViewById(R.id.textView)
        //之後每次這個變數呼叫方法或函數都需要安全呼叫「?」
         val length = textView?.text?.length
    }
}

由上可知這樣的確很麻煩一直要對其可空性做處理。
所以,我們還有其他選擇:

  • lateinit 延遲初始化
  • lazy properties 惰性屬性

lateinit 延遲初始化

lateinit關鍵字可以用在頂層變數或區域變數。這是告訴kotlin我們之後就會初始化它了,不要催我現在就給值的意思,延續上例是這樣使用的:

class MainActivity : AppCompatActivity() {
    //var 關鍵字前標明lateinit
    private lateinit var textView: TextView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //初始化
        textView = findViewById(R.id.textView)
        //可以正常呼叫方法了,不需要一直處理可空性啦~
        val textlength = textView.text.length
        Log.d("mainActivity", "onCreate: $textlength")
    }
}

雖然好用但也有其需要注意的點:

  1. 只能搭配var關鍵字定義的變數,且不可為原始類型(primitive types)。
  2. 在任何地方呼叫變數前一定要先確認該變數已完成初始化,因為你已經向編譯器保證了會初始化,如果在初始化前呼叫了該變數,編譯器不會檢查,所以,無法保證其安全性。

檢查是否初始化:

避免沒有初始化或重複初始化。
這應該是固定的語法if(::該變數名.isInitialized) 意思是:如果變數已經初始化的話...
為了偷懶方便,我以上面textView舉例,一般不需要這樣寫:

if(!::textView.isInitialized) textView = findViewById(R.id.textView)

lazy properties

第二種避免使用可空類型的方式:lazy properties, lazy()是一個接受 lambda 並返回實例的函數,第一次呼叫該屬性的getter時,會執行lambda,傳遞給lazy()函數並記住結果。後續在呼叫getter時,就只會返回記住的結果。
看官方網站給的例子:

val lazyValue: String by lazy {
    println("computed!")
    "Hello"  //呼叫getter時的返回值
}

fun main() {
    println(lazyValue)
    println(lazyValue)
    //結果:
    //computed!   (初始化1次)
    // Hello       
    // Hello      (第2次就只返回記住的值,並不會再次執行初始化)

}

需要注意 :

  • Lazy properties只能搭配val關鍵字使用,只有getter沒有setter。
  • 初次使用就是初始化,不使用就不會初始化。

小結

  • lateinit 只能搭var ,而 lazy 只能配 val
  • lateinit 須自己決定初始化時機,編譯器不管你; lazy 則是初次使用就會依照lambda返回值初始化
  • 兩者都不需要使用安全呼叫運算子「?」

參考
kotlin文檔 Lateinit top-level properties and local variables
kotlin文檔 lazy-properties
Khan Academy - lateinit
Kotlin使用心得(十一):lateinit vs lazy


上一篇
第24天 Kotlin小學堂(13) : null安全與異常
下一篇
第26天 Kotlin小學堂(15) :標準函數
系列文
新手向Android&Kotlin學習紀錄30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言