| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- hidden-api
- Inner Class
- java
- memory leak
- 구현
- broadcastAsUser
- programmers
- compose
- 삽질로그
- ARRANGEMENT
- NextPermutaion
- FCM
- Alignment
- 프로그래머스
- BFS
- JetpackCompose
- Android
- 알고리즘
- Today
- Total
undefined
[Android] 중첩된 뷰가 닫히지 않을 때 본문
근래 가장 나를 힘들게 했던 문제가 있었다. 아마 나중에 또 만나게 될 것 같아서 정리해보려고 한다.
이번에 구현해야 하는 기능 중 하나는 특정 주기마다 백그라운드에서 작업을 하고 완료되면 사용자에게 팝업으로 알리는 것이었다.
그냥 팝업을 띄우는 데 까지는 크게 어려움이 없었다. 하지만 해결하기 어려웠던 문제 중 하나가 바로 팝업이 중첩되었을 때 비정상적인 동작을 하는 것이었다.
대략, 특정 동작이 완료되면 -> 서비스를 실행하고, 조건에 맞는 분기를 타서 -> 뷰를 뿌려주고 -> 사용자의 동작에 따른 작업 + 뷰 닫기+ 서비스 종료 와 같은 프로세스를 타는 기능이다. 그런데 마지막 팝업의 닫기가 동작하지 않았다 (뷰의 다른 버튼들이나 창 드래그는 잘 됐다. 하지만 이 문제의 뷰는 재부팅 할 때 까지 사라지지 않았다).
원인은 각 팝업에 대한 정보를 별도로 관리하지 않아서 발생한 문제였다.
어떻게 보면 굉장히 당연한 문제였는데 찾는게 쉽지 않았다.
결론적으로 하나의 서비스가 시작되면서 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()
}
'삽질로그' 카테고리의 다른 글
| [ANDROID] 백그라운드 상태에서 fcm메시지 알림 띄워주기 (0) | 2023.09.17 |
|---|