혹시 어떤 변수를 선언하는데 바로 할당할 수는 없고 초기 값으로 null 을 주기는 싫은 상황이 있지 않았나요? 보통 이런 상황에서 늦은 초기화로 lateinit 또는 lazy 를 사용합니다. 둘 다 똑같은 늦은 초기화인데 어떤 걸 선택할지 각각 특징...

[안드로이드] 코틀린 늦은 초기화 lateinit, lazy 선택하기

혹시 어떤 변수를 선언하는데 바로 할당할 수는 없고

초기 값으로 null 을 주기는 싫은 상황이 있지 않았나요?

보통 이런 상황에서 늦은 초기화로 lateinit 또는 lazy 를 사용합니다.

둘 다 똑같은 늦은 초기화인데 어떤 걸 선택할지 각각 특징을 알고 선택해야 될 것 같습니다.

 

 




1. 늦은 초기화 예시 : 데이터 바인딩

데이터 바인딩을 위해 binding 이라는 변수를 늦은 초기화(lateinit / lazy)를 활용하여 작성하였습니다.

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

    ...
}

 

private val binding: ActivityMainBinding by lazy {
DataBindingUtil.setContentView(this, R.layout.activity_main)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

...
}


해당 소스는 둘 다 문제 없이 동작합니다.

"그럼 어떤 소스가 더 좋을까?" 라는 고민을 합니다.

선택하기 전에 lateinit 과 lazy 차이점을 알아보겠습니다.





2. lateinit

lateinit var text: String

 - 변경 가능한 var 와 함께 사용

 - 반드시 최초 초기화 후 호출해야 함

 - primitive type (Int, Float, Long 등) 사용 불가능

 

 

 

 

3. lazy

private val textLength: Int by lazy {
println("최초 호출 시 한번")
text.length
}

 

 - 변경 불가능한 val 와 함께 사용

 - 최초 호출 시 lazy 블록 안에 동작과 함께 초기화된 값을 저장하며, 그 이후 호출은 단순히 저장된 값을 반환

 - primitive type (Int, Float, Long 등) 사용 가능

 

 

 

 

3. 선택

제가 사용할 binding 은 한번 할당 받은 view 데이터를 계속해서 사용할 것이기 때문에 lazy 가 적합하다고 판단합니다.

private val binding: ActivityMainBinding by lazy {
DataBindingUtil.setContentView(this, R.layout.activity_main)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

...
}

 

사실 기존에 lateinit 만 사용해왔는데... 

이번에 정리를 통해서 lateinit 과 lazy 특징을 알고 

상황에 맞게 쓰면서 누군가 봤을 때 좀 더 설득력 있는 코드가 되야겠다는 생각을 하게 됩니다. 

(반성 중)


 


 

[Reference]

lateinit vs lazy 정확히 아세요?

lateinit과 lazy란? - 지연 초기화를 통한 성능 개선




0 comments: