본문 바로가기
Android

[안드로이드] Fragment에서 뒤로가기 처리하기 - onBackPressedDispatcher

by JongSeok 2023. 2. 1.

안드로이드 앱을 개발하다 보면 하나의 액티비티와 다수의 프래그먼트의 구성으로 개발하는 경우가 있습니다.

 

액티비티로만 구성된 화면의 경우 액티비티 위에 다른 액티비티가 쌓이는 방식이기 때문에 기기 메뉴바의 뒤로 가기 즉, onBackPressed()가 실행되면 최상단의 액티비티가 제거되면서 의도한 뒤로 가기가 정상적으로 작동합니다.

혹은 액티비티에서 뒤로 가기의 설정을 변경하기 위해 onBackPressed()를 override하여 필요에 따라 수정할 수 있습니다.

 

하지만 프래그먼트에서 뒤로 가기를 의도하기 위해 액티비티처럼 onBackPressed()를 찾는다면 해당 메소드를 찾을 수 없습니다.

 

이를 해결하기 위해 프래그먼트가 속한 액티비티에서 인터페이스를 정의해 인터페이스에서 onBackPressed를 재정의하고, 프래그먼트에서 액티비티의 인터페이스를 상속받아 해결하는 방법이 있습니다.

이 방법외에 뒤로 가기를 의도하려는 프래그먼트 내에서 해결하는 방법을 찾아보았습니다.


override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    ...
        
    requireActivity().onBackPressedDispatcher.addCallback(object: OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // 뒤로 가기 시 실행되는 코드
            requireActivity().supportFragmentManager.beginTransaction().remove(this@SearchFragment).commit()
        }
    })
}

해결방법은 onBackPressedDispatcher입니다.

 

API레벨 33부터 onBackPressed가 deprecated되고, 대신 onBackPressedCallback을 사용할 것을 안드로이드 공식문서에서 권장하고 있습니다.

 

먼저 onBackPressedCallback의 추상클래스인 handleOnBackPressed를 재정의합니다.

그리고 이 콜백 객체를 BackPressedDispatcher에 등록해주는 방식으로 사용할 수 있습니다.


추가!!

위의 방법으로 구현시 프래그먼트가 여러개가 쌓이는 경우에는 handleOnBackPressed에 대해 "not attached to an activity" 에러가 발생했습니다.

아마 프래그먼트가 하나의 액티비티 위에 쌓이면서 뒤로가기 이벤트 발생 시 최상위 프래그먼트로 전달되지 않아(?) 발생하는 오류인 것 같습니다.

 

해결방법은 다음과 같습니다.

private lateinit var callback: OnBackPressedCallback

전역 변수로 OnBackPressedCallback 객체를 지연생성합니다.

override fun onAttach(context: Context) {
    super.onAttach(context)

    callback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // 뒤로가기 클릭시 동작하는 로직
            requireActivity().supportFragmentManager.beginTransaction()
                .setCustomAnimations(0, R.anim.horizon_exit_front)
                .remove(this@CartFragment)
                .commit()
        }
    }
    requireActivity().onBackPressedDispatcher.addCallback(this, callback)
}

해당 콜백을 onAttach에서 object로 정의해 onBackPressedDispatcher를 통해 콜백을 호출합니다.

 

이제 프래그먼트가 많이 쌓이더라도 뒤로가기가 정상적으로 작동합니다 :)

728x90
반응형