Kotlin lazy and lateinit


Kotlin lazy and lateinit

在 Kotlin 中當我們宣告變數時需要給他一個初始值,如果一開始無法給他初始值則必須先宣告成 Nullable type 並且要宣告成 var ,但這樣不是很方便,因為我們實際上是需要他是 Non-null type 只是我們沒那麼快給他初始值


舉個例子,這是一個 Java 的 Activity

// Java code
public class MainActivity extends Activity {
    
    private Button button;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        button.setText("HELLO");
    }
}

由於 Java 變數都是 Nullable type 的,所以當中的 button 這樣寫沒什麼問題,現在我們簡單轉換成 Kotlin 的方式看看

// Kotlin code
class MainActivity : AppCompatActivity() {

    private var button: Button? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button = findViewById(R.id.button)
        button?.text = "HELLO"
    }
}

聰明如你馬上發現奇怪的地方,這樣我們每次呼叫 button 不就都要加上問號了嗎,為了解決這個問題這時可以使用 lazy or lateinit

lateinit var


如果你確定這個變數你一定會初始化那你可以使用 lateinit var 來延遲初始化這個動作

// Kotlin code
class MainActivity : AppCompatActivity() {

    private lateinit var button: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button = findViewById(R.id.button)
        button.text = "HELLO"
    }
}

這樣不就很好的解決我們的問題了嗎,此時的 button 是 Non-null type 使用上再也不用加上問號了~

要注意的是 lateinit 只能用在 var 上否則編譯時期會出現 'lateinit' modifier is allowed only on mutable properties

lateinit 也不能使用基本型態 ex: Int

如果你不確定有沒有被初始化過也可以用 isInitialized 判斷他有沒有被初始化過

if (this::button.isInitialized == false) {
    // 還沒初始化喔
}

by lazy


by lazy 會在第一次呼叫到的時候才會初始化並且就只會初始化這麼一次,與 lateinit 不同的是 by lazy 必須是 val 而 lateinit 必須是 var

// Kotlin code
class MainActivity : AppCompatActivity() {

    private val button: Button by lazy { 
        findViewById(R.id.button) 
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button.text = "HELLO"
    }
}

要注意的事情 by lazy 的變數,第一次被呼叫的時候才會初始化因此不適合放一些跑很久的程式碼,也要注意生命週期的問題避免程式跑起來時遇到邏輯錯誤

到這裡就大致介紹完 lazy and lateinit 啦~謝謝各位收看


WRITTEN BY
Aki

熱愛寫code的開發者,專注於 Android 手機 Native App 開發,對於 IOS 也有涉略。閒暇之餘也學習 JavaScript 等前端框架