// dialog 를 프로퍼티(멤버변수)로 선언했다고 가정
dialog?.dismiss()
dialog = Dialog()
dialog?.show(xxxFragmentManager, dialogTag)
위와 같은 코드가 있다.
대략적인 의미를 보면
1. dialog null 이 아니라면 dismiss 시키고
2. dialog 를 초기화 하고
3. 마지막으로 다이얼로그를 보여준다.
잘 작성한 코드로 다이얼로그가 중복으로 뜨는일은 없을 것 같이 느껴진다.
하지만 Configuration change(퍼미션 변경, 화면 변경, 언어 변경 등), OOM 가 일어나면 문제가 생기게 된다.
보통 안드로이드 이론 공부하면, Configuration change 가 일어나면 액티비티가 다시 시작되는 것을 우리는 알고 있다.
따라서 onSaveInstanceState 에서 Bundle 에 필요한 것을 저장하고 onRestoreInstanceState에서 필요한 정보를 복구 해서 사용한다고 알고 있다 (현재는 Bitmap 같은 메모리를 많이 잡아먹는 아이템은 Bundle 에 직렬화 / 역직렬화 하는 것도 오버헤드가 크게 때문에 뷰모델을 추천하고 있다)
하지만 실제로 코드를 작성할 때는 빼먹게되는 부분이 많은 것 같다.(OOM, Configuration change 를 고려하지 않는 다던가, 문제를 인지해도 발생빈도가 낮아서 현실과 타협하며 넘어간다던가)
내가 경험했던 사례는
Permission 을 허용했던 유저가 앱을 Background 로 보내고 설정 -> 앱 정보를 통해 Permission 을 거부하고 앱을 다시 Forerground 로 올렸을 때, 앱 프로세스가 바로 죽으면서 다시 시작되게 되는데
Permission 은 내부에서 Configuration change 와 조금 다르게 처리되는지 onDestroy 가 항상 호출되지 않았고, 결과적으로 onDestroy 에 dialog?.dimiss() 같은 방어 코드를 작성하였어도 호출되지 않으니 프로세스 죽기 전 다이얼로그가 사라지지 않았고,
DialogFragment transaction 들이 복구 되어 이전 다이얼로그가 보여지고, 그 상태에서 앱이 onCreate 부터 다시 시작되어
dialog?.dismiss()
dialog = Dialog()
dialog?.show(xxxFragmentManager, dialogTag)
dialog 는 null 이기 때문에 dismiss 는 호출되지 않고, 다이얼로그가 초기화 되고 show 메서드를 만나 보여지게 되어
최종적으로 2개의 다이얼로그가 중복되어 보였다.
결과적으로 이 문제를 해결하기 위해
xxxFragmentManager 에서 tag, id(findFragmentByTag, findFragmentById) 로 dialogFragment 가 이미 만들어져있는지 확인한 뒤 다이얼로그를 보여줄지 말지 결정하는 식으로 코드를 변경하게 되었다.
이런 문제를 해결하며, 좀더 성숙한 주니어가 되기 위해서는 머리속으로 "이런 유저들이 발생하지 않을까?" 생각이 들었을 때 적은 비율이니까 괜찮겠지. 같은 식으로 넘어가지 않고, 더욱 문제를 파고들어 해결해 유저들에게 더욱 신뢰있는 서비스를 제공해야겠다는 다짐을 했다.
이것만 지켜져도 2021년은 만족스러운 해가 될 것이다.
참고
'Android > Development Tips' 카테고리의 다른 글
Bitmap, contentUri 를 Retrofit RequestBody 에 담을 때 Tips (1) | 2021.05.17 |
---|---|
Hilt 수박 겉핥기 (0) | 2021.05.07 |
java.lang.IllegalStateException: Software rendering doesn't support hardware bitmaps 에러 수정하기 (1) | 2021.01.10 |
다양한 뷰타입을 가지는 Recyclerview 만들기 (0) | 2020.12.26 |
Clean Architecture (무비 앱) (0) | 2020.04.26 |