Deprecated된 안드로이드 메소드, setHasOptionsMenu(), onCreateOptionsMenu(), 그리고 onOptionsItemsSelected()를 대체하여 툴바 옵션 메뉴를 초기화하는 새로운 방법을 정리
Deprecated 코드 발견
Trindex 안드로이드 앱의 차기 업데이트를 준비하면서 AppCompat을 최신 안정화 버전인 1.7.0으로 적용해 주었다. 그러자 툴바 옵션 메뉴와 관련된 다음 메소드 3개가 deprecated 되는 것을 확인할 수 있었다.
관련 내용을 확인해 보니 androidx.fragment에서는 이미 1.5.0-alpha05 버전부터 deprecated 되었던 내용이다. 그게 벌써 2022년 상반기의 일인데, AppCompat에는 이제서야 적용이 된 듯하다.
https://developer.android.com/jetpack/androidx/releases/fragment?hl=ko
안드로이드의 공식 가이드라인
가이드라인에 따르면 deprecated된 부분은 다음(43~55번)과 같이 대체해 주면 된다고 한다.
액티비티와 프래그먼트 중 프래그먼트에 대한 가이드라인이라서 onViewCreated() 콜백 메소드 내에 구현하고 있는 것을 볼 수 있다. Trindex 앱의 경우 여러 개의 프래그먼트로 구성되어 있고, 각 프래그먼트 마다 서로 다른 툴바 옵션 메뉴가 구성되는 형태이기에 이를 참고하여 작성했다.
[사용자 수식]이라는 새로운 프래그먼트에 적용해 보았는데, 일단 별다른 문제 없이 잘 구현되는 듯 보였다. 하지만...
새로운 문제 발생
다른 프래그먼트로 이동하자 예상치 못한 문제가 발생했다. [사용자 수식] 프래그먼트의 툴바 옵션 메뉴가 그다음에 열린 [데이터 시트] 프래그먼트의 메뉴에 추가되어 나오는, 툴바 옵션 메뉴 누적 현상이 발생한 것이다.
문제의 원인
몇 가지 테스트를 통해 문제의 원인을 알게 되었다.
Trindex는 위와 같이 show() / hide()를 이용해 이미 만들어진 프래그먼트 간의 이동을 처리한다. 이는 이미 열린 프래그먼트의 내용을 유지함으로써 서로 간의 데이터를 사용자가 비교할 수 있도록 구현한 것인데, 이는 다음에서 제시하는 구글의 권장 방식과 달리,
프래그먼트 생명주기 관련 메소드가 콜백 되지 않는 방식이다. 따라서 프래그먼트 전환 시 프래그먼트의 onResume() 콜백이 발생하지 않기 때문에 앞서 세 번째 스크린샷의 Lifecycle.State.RESUMED가 의미 없게 되어버린다.
https://developer.android.com/guide/fragments/transactions?hl=ko#java
해결 방법
프래그먼트 전환에 대한 구글의 가이드라인을 준수하고, 대신 onSaveInstanceState() 콜백 메소드의 Bundle을 잘 이용해서 프래그먼트의 상태를 유지하는 것으로 이 문제를 해결할 수도 있을 것이라는 생각이 들었다. 하지만 유지가 필요한 파라미터 중 그래픽적인 요소들이 많아 까다롭기도 하고, 또, show() / hide()만의 기민한 움직임을 포기하기도 아쉬웠기에 결국 다음과 같은 방법을 사용하기로 했다.
먼저 각 프래그먼트 별로 MenuProvider 인스턴스를 멤버로 만들어 준다.
onViewCreated()에서는 위와 같이 툴바 옵션 메뉴에 대한 초기화 코드를 입력해 준다.
그리고 각 프래그먼트에 onHiddenChanged() 콜백 메소드를 오버라이딩 해준다. 프래그먼트의 hidden 여부에 따라 옵션 메뉴를 제거하거나 다시 등록해 주는 것이다.
만일의 경우를 대비해서 프래그먼트가 파괴되는 시점에 툴바 옵션 메뉴가 제거될 수 있도록 코드를 추가해 주기도 했다.
모든 프래그먼트에 대해 위와 동일한 처리를 해준 뒤 다시 실행을 해 보면 더 이상 툴바 옵션 메뉴가 누적되거나 하는 일 없이 깔끔하게 동작하는 것을 확인할 수 있다.
마치며...
문제는 해결되었지만 이는 구글 가이드라인을 벗어난 방법이라 100% 안전하다고 장담할 수는 없다. 때문에 이를 염두에 두고 향후 어떠한 문제가 발생했을 시 이와 연관성은 없는지 항상 체크해 볼 일이다.