Tìm hiểu về lateinit và lazy trong Kotlin

I, Late-initialized variable

  • Thông thường, trong kotlin các non-null member variable phải được khởi tạo khi khai báo. Tuy nhiên, trong nhiều trường hợp điều này không thuận tiện.
  • Kotlin cungx cho phép member variable khởi tạo sau bằng lateinit (late initialization) keyword.
  • Ví dụ 1: property được khởi tạo thông qua dependency injection hoặc trong setup() của unit test. Chúng ta có thể sử dụng lateinit để khai báo biến:
1
2
3
4
5
6
7
8
9
10
11
public class MyTest {
lateinit var subject: TestSubject

@SetUp fun setup() {
subject = TestSubject()
}

@Test fun test() {
subject.method() // dereference directly
}
}
  • Khi dùng lateinit chúng ta cần tuân theo các quy định sau:
    • 1, Chỉ được dùng với var tạo thành lateinit var cho property ở trong class body.
    • 2, Không được dùng trong constructor và method.
    • 3, Chỉ dùng cho các property không có custom getter và setter.
    • 4, Chỉ dùng cho các property không null và không phải là primitive type.
  • Nếu truy cập lateinit var property trước khi nó được khởi tạo, chúng ta sẽ gặp exception.
  • Do đó, để tránh exception chúng ta nên xác định xem lateinit var property đã được khởi tạo chưa.
  • Để xác định lateinit var property đã được khởi tạo chưa, chúng ta sử dụng isInitialized như sau:
1
2
3
4
5
6
7
lateinit var bar: Bar

fun test() {
if (::bar.isInitialized) {
println(foo.bar)
}
}

II, Lazy variable

  • Đôi khi chúng ta muốn member variable được khởi tạo khi chúng ta cần dùng đến nó.
  • Trong trường hợp như vậy chúng ta có thể sử dụng lazy property thông qua lazy().
  • lazy() là 1 function có tham số là 1 lambada và trả về 1 Lazy object:
    • Lần đầu tiên gọi get() của property thì biểu thức lambada của lazy() sẽ được xử lý, khởi tạo và ghi nhớ giá trị cho property đó.
    • Các lần gọi get() tiếp theo, property sẽ lấy giá trị được ghỉ nhớ đó (không cần thực hiện lại lambada).
  • Ví dụ 2: Lần đàu tiên sử dụng name, lambada được xử lý do đó name = It life, đồng thời giá trị được ghỉ nhớ. Các lần sử dụng name tiếp theo thì vẫn có giá trị là It life:
1
2
3
public class Test{
val name: String by lazy { “It life” }
}
  • lazy() chỉ dùng cho các val property.