반응형

Android App을 개발하다 보면 화면을 구성할 때 하나의 액티비티에 다수의 프래그먼트를 사용해서 구성하는 경우가 많습니다.

 

그러나 안드로이드의 Fragment에는 Activity의 onBackPressed()와 같은 콜백 메소드가 없기 때문에 별도의 리스너를 만들어 액티비티에서 back press 이벤트가 발생했을 시 해당 프래그먼트에서 구현한 콜백 함수를 호출하는 형식으로 구현해주는 방법 등 야매스러운(?) 방법들을 사용했어야만 했습니다. 하지만 이 방식은 프래그먼트의 생명주기를 잘 관리하면서 사용해야 한다는 단점이 있었습니다.

 

그렇다면 정녕 방법이 없는 걸까요? 아닙니다. 다행스럽게도 Androidx 패키지에서 이에 대한 대책이 나왔습니다. 바로 OnBackPressedDispatcher() 입니다.

 

OnBackPressedDispatcher()

Fragment 에서는 OnBackPressedCallback 객체를 생성하여 액티비티에 addCallback() 해주면 되는데요.

예제를 통해 살펴보도록 하겠습니다.

 

fragment_sample.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SampleFragment">

    <TextView
        android:id="@+id/sample_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="back press event not yet." />

</FrameLayout>

 

SampleFragment.kt

class SampleFragment : Fragment() {
    private lateinit var callback: OnBackPressedCallback
    
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_sample, container, false)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        callback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                sample_text.text = "occur back pressed event!!"
            }
        }
        requireActivity().onBackPressedDispatcher.addCallback(this, callback)
    }

    override fun onDetach() {
        super.onDetach()
        callback.remove()
    }
}

 

간단합니다! OnBackPressedCallback 객체를 선언하여 onAttach() 에서 BackPressedDsipatcher에 등록해주고, onDetach()에서 제거해주었습니다.

 

그리고 callBack이 잘 동작하는지 확인하기 위해 간단하게 텍스트뷰 하나 두고서 Back Press 이벤트 발생했을 시에 텍스트뷰의 텍스트를 "occur back pressed event!!"로 바꿔보도록 코드를 작성해봤습니다.

 

Fragment에서 Back Press를 처리하기 위해서는 2가지만 신경 써주시면 되는데요.

 

하나는 OnBackPressedCallback 추상 클래스의 handleOnBackPressed() 를 재정의하여 해당 메소드 내에 내가 처리하고자 하는 로직을 넣어주는 것입니다.

 

그리고 이 콜백 객체를 이제 액티비티의 BackPressedDispatcher에 등록해줘야 하는데요. 그 부분이 바로 가장 아래에 있는 requireActivity().onBackPressedDispatcher.addCallback() 입니다. 여기서 천 번째 파라미터는 LifecycleOwner 타입을 필요로 하기 때문에 일반적으로 프래그먼트 객체를 넘겨주면 되고, 두 번째 파라미터에 앞서 만든 콜백 객체를 넘겨주면 됩니다.

 

그러면 이제 액티비티에서 OnBackPress() 이벤트 발생 시 BackPressedDispatcher에 등록된 리스너들 중 생명주기의 상태가 Alive 상태의 콜백 리스너들만 실행하게 됩니다.

 

이때 주의할 점은, 만약 액티비티의 onBackPress() 함수를 Override 하여 super.onBackPressed()를 호출하지 않도록 한다면 BackPressedDispatcher 또한 동작하지 않기 때문에 유의해야 합니다.

 

결과 화면

 

위 예제에 대한 전체 코드는 Github 저장소에서 확인할 수 있습니다.


 

반응형
반응형