본문으로 바로가기
internal class CustomDialog : DialogFragment() {
    private val items: List<View> by lazy {
    	listOf(
                item_a,
                item_b,
                item_c,
                item_d,
                item_e,
                item_f
        )
    }
    
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_item, container, false)
    }
    
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        items.forEachIndexed { index, item ->
            item.setOnClickListener {

            }
        }
    }
}
    
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_item, container, false)
    }
    
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        items.forEachIndexed { index, item ->
            item.setOnClickListener {

            }
        }
    }
}

Xml의 반복적인 뷰들을 클릭 시 index 별로 별도의 처리를 하고 싶은 경우가 있어서

해당 View 들을 by lazy로 초기화하여 사용하였다. 

private fun showDialog() {
    if(cusomDialog == null) {
        cusomDialog = CustomDialog()
    }

    if(!cusomDialog!!.isAdded && !cusomDialog!!.isVisible) {
        cusomDialog!!.show(supportFragmentManager, TAG)
    }
}

보여주고자 하는 Dialog가 null일 경우 새로 생성해서 보여주고 null이 아닌 경우에 재사용을 하는 방식을 사용하였지만

실제 실행 시에 빠르게 클릭하여 Dialog 생성 시 View 클릭 시에 해당 클릭 리스터가 제대로 동작하지 않는 버그가 있었다.

 

디버깅 결과 평소에는 잘 작동하다가 빠르게 클릭할 경우에만 발생하는 것은 평소에는 Dialog 인스턴스가 GC에 의해 제거되어서 새로운 객체가 생성됬지만 빠르게 클릭하여 Dialog가 이전의 Dialog 인스턴스를 사용하여 발생한 버그였다.

 

이렇게 재사용된 Dialog의 Property인

private val items: List by lazy {...} 로 인해 이미 items가 할당이 되었지만 실제 View 들은

show를 할 경우 Fragment의 생명주기에 따라 onCreateView가 실행되면서 새로운 View가 화면에 보이게 되어

실제 Dialog에 보여지는 View와 items 변수와 할당된 View가 다르면서 생기는 버그였다.

 

internal class CustomDialog : DialogFragment() {
    private lateinit var items: List<View>
    
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_item, container, false)
    }
    
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        
        items = listOf(
                item_a,
                item_b,
                item_c,
                item_d,
                item_e,
                item_f
        )

        items.forEachIndexed { index, item ->
            item.setOnClickListener {

            }
        }
    }
}

위 와 같이 lateinit을 이용하여 생명주기 마다 초기화하여 해당 문제를 해결하였다.