Android/Development Tips

DialogFragment 를 상속하는 다이얼로그에서 dismiss 할 때 Tips

Nanamare 2021. 1. 10. 23:55
728x90
// 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년은 만족스러운 해가 될 것이다.

 

참고

developer.android.com/guide/fragments/dialogs?authuser=1

728x90