Notice
Recent Posts
Recent Comments
Link
«   2026/08   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
Archives
Today
Total
관리 메뉴

undefined

[Android] 중첩된 뷰가 닫히지 않을 때 본문

삽질로그

[Android] 중첩된 뷰가 닫히지 않을 때

un-defined 2023. 9. 10. 20:44

근래 가장 나를 힘들게 했던 문제가 있었다. 아마 나중에 또 만나게 될 것 같아서 정리해보려고 한다.

 

이번에 구현해야 하는 기능 중 하나는 특정 주기마다 백그라운드에서 작업을 하고 완료되면 사용자에게 팝업으로 알리는 것이었다.

 

그냥 팝업을 띄우는 데 까지는 크게 어려움이 없었다. 하지만 해결하기 어려웠던 문제 중 하나가 바로 팝업이 중첩되었을 때 비정상적인 동작을 하는 것이었다.

대략, 특정 동작이 완료되면 -> 서비스를 실행하고, 조건에 맞는 분기를 타서 -> 뷰를 뿌려주고 -> 사용자의 동작에 따른 작업 + 뷰 닫기+ 서비스 종료 와 같은 프로세스를 타는 기능이다. 그런데 마지막 팝업의 닫기가 동작하지 않았다 (뷰의 다른 버튼들이나 창 드래그는 잘 됐다. 하지만 이 문제의 뷰는 재부팅 할 때 까지 사라지지 않았다).

 

원인은 각 팝업에 대한 정보를 별도로 관리하지 않아서 발생한 문제였다.

 

어떻게 보면 굉장히 당연한 문제였는데 찾는게 쉽지 않았다.

 

결론적으로 하나의 서비스가 시작되면서 A 뷰를 그렸다고 치면, 다시 서비스가 호출되면서 A 뷰에 대한 참조를 잃고 B뷰를 다시 그린것이다. 그래서 닫기를 눌렀을 때 B만 닫히고 서비스를 종료해버리면서 A뷰가 남게 된 것이다.

 

따라서 서비스가 실행되며 생성되는 뷰와 뷰의 상태(파라미터, 위치값) 을 가지는 객체를 만들고, 이 객체들을 관리하는 리스트를 서비스 내의 전역 변수로 만들었다. 그리고 서비스가 실행되며 뷰를 생성할 때 마다 새로운 객체를 만들고 해당 객체에 저장하여 관리하도록 수정하였다.

    data class PopupInfo(
        val rootView: View,
        val params: WindowManager.LayoutParams,
        var initialX: Float = 0f,
        var initialY: Float = 0f
    )
    private val activePopups: MutableList<PopupInfo> = mutableListOf()

	override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        ...
        val popupInfo = PopupInfo(rootView, params!!)
        ...
        activePopups.add(popupInfo)
    }


    fun closeViewOrStopService(popupView: View){
		...
                try {
                    windowManager!!.removeView(popupView)
                    activePopups.removeIf { it.rootView == popupView }
                } catch (e: IllegalArgumentException) {
                    e.printStackTrace()
                }
		...
        if(activePopups.isNullOrEmpty()) stopSelf()
    }

 

반응형
Comments