onBackPressed 대체

기존까지는 현재 액티비티를 종료하는 경우에는 단순히 onBackPressed()를 호출하엿다. 하지만 onBackPressed() 메서드는 기본적으로 현재 액티비티에서만 동작한다. 현재 액티비티가 스택의 가장 맨 위에 있지 않다면, 뒤로가기 버튼을 눌렀을 때 이전 액티비티가 실행되는 것이 아닌, 현재 액티비티가 종료되는 문제가 발생할 수 있다.

안드로이드 12 이후 변경

https://developer.android.com/about/versions/12/behavior-changes-all?hl=ko#activity-lifecycle

안드로이드 12에서는 작업의 루트에 있는 런처 액티비티에서 시스템의 뒤로 누르기의 기본 처리를 변경하였다. 이전 버전에서는 뒤로 누르면 이러한 액티비티를 완료하였다. 하지만 12부터는 액티비티를 완료하는 대신 액티비티와 그 작업을 백그라운드로 이동한다. 대부분의 앱에서 이 변경사항으로 인해 '뒤로'를 사용해서 앱 외부로 이동하는 사용자는 콜드 상태에서 앱을 완전히 다시 시작할 필요 없이 웜 상태에서 더 빠르게 앱을 재시작할 수 있다.

onBackPressed()를 재정의하는 대신 맞춤 뒤로 탐색을 제공 하는 AndroidX Activity API를 사용하는 것이 좋다. AndroidX Activity API는 시스템 뒤로 누르기를 가로채는 구성요소가 없으면 자동으로 적절한 시스템 동작을 따른다.

이러한 문제를 해결하기 위해 OnBackPressedDispatcher를 제공한다. 이를 사용하면 현재 액티비티가 스택에서 가장 위에 있지 않더라도, 뒤로가기 버튼을 눌렀을 때 이전 액티비티가 실행된다.

OnBackPressedDispatcher

https://developer.android.com/guide/navigation/navigation-custom-back?hl=ko

OnBackPressedDispatcher는 뒤로 버튼 이벤트가 하나 이상의 OnBackPressedCallback객체로 전달되는 방법을 제어한다. 콜백이 사용 설정되면 디스패처가 콜백의 handleOnBackPressed()를 호출하여 뒤로 버튼 이벤트를 처리한다.

콜백은 addCallback 메서드를 통해 추가된다. LifecycleOwner를 취하는 addCallback()메서드를 사용하는 것이 좋으며 이렇게 하면 Lifecycle.State.STARTED일 때만 OnBackPressedCallback이 추가되도록 할 수 있다.

class MyFragment : Fragment() {
		private lateinit var callback: OnBackPressedCallback

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
				
				requireActivity().onBackPressedDispatcher.addCallback(this@SearchFragment){
                if (svKeyword.isShowing){
                    binding.svKeyword.hide()
                }
                else {
                    activity?.finish()
                }
            }
        
		}
}

콜백은 addCallback()을 통해 추가할 때 LifecycleOwner가 Lifecycle.State.STARTED 상태에 진입할 때까지 책임 연쇄에 추가되지 않는다.

여러 개의 다른 중첩된 수명 주기 소유자에 등록된 콜백이 있다면 위에서 설명한 순서를 유지하는 것이 특히 중요하므로 OnBackPressedCallback의 사용 설정 상태를 변경하는 것은 일시적인 변경이 좋습니다.

그러나 OnBackPressedCallback을 전체적으로 삭제하려는 경우 remove()를 호출해야 합니다. 하지만, 콜백은 연결된 LifecycleOwner가 제거될 때 자동으로 삭제되므로 일반적으로 필수사항은 아닙니다.