혹시 어떤 변수를 선언하는데 바로 할당할 수는 없고
초기 값으로 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과 lazy란? - 지연 초기화를 통한 성능 개선
0 comments: