onBackPressedDispatcher이란?
안드로이드에서 애플리케이션을 개발하다보면, 종종 Activity 혹은 Fragment에서 뒤로 가기 버튼에 대한 동작을 커스텀하게 정의해야 할 상황이 발생한다. 이렇게 뒤로 가기 버튼에 대한 동작을 커스텀하게 정의해야 할 때, Activity 혹은 Fragment에서 접근할 수 있는 onBackPressedDispatcher를 사용할 수 있다.
*onBackPressedDispatcher 변수는 OnBackPressedDispatcher 객체를 가리킨다.
onBackPressedDispatcher 사용해 뒤로가기 동작 설정하기
onBackPressedDispatcher를 사용해 뒤로 가기 동작을 정의하기 위해서는 두가지가 필요하다. onBackPressedDispatcher의 뒤로 가기 이벤트를 핸들링할 LifecycleOwner(일반적으로 Activity 혹은 Fragment)와 뒤로 가기 버튼이 눌렸을 때 어떤 동작을 할지 설정하는 OnBackPressedCallback 객체이다.
OnBackPressedCallback 객체 만들기
OnBackPressedCallback 객체는 추상 클래스로 정의된 클래스로 직접 구현체를 만들어도 되지만, 일반적으로 Activity, Fragment 안에 익명 객체로 만든다.
public abstract class OnBackPressedCallback {
...
public OnBackPressedCallback(boolean enabled) {
mEnabled = enabled;
}
@MainThread
public abstract void handleOnBackPressed();
...
}
익명 객체로 생성 시 OnBackPressedCallback가 사용 가능한지를 나타내는 enabled 변수를 설정해야 하며, handleOnBackPressed() 함수를 구현해야 한다. 따라서 이를 익명 객체로 만들면 다음과 같은 모양이 된다.
private val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// 뒤로 가기 버튼이 눌렸을 때 실행할 코드
}
}
만약 뒤로가기 버튼이 2초 안에 두 번 눌렸을 때, 앱을 종료하도록 만들고 싶다면 다음과 같이 만들면 된다.
private var lastBackPressedTime = 0L
private val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (lastBackPressedTime > System.currentTimeMillis() - 2000) {
finish()
} else {
Toast.makeText(this@MainActivity, "앱을 종료하려면 뒤로 가기를 한 번 더 눌려주세요", Toast.LENGTH_SHORT).show()
lastBackPressedTime = System.currentTimeMillis()
}
}
}
* 만약 뒤로 가기 동작을 기존과 같이 하도록 만들고 싶으면 다음과 같이 만들면 된다.
private val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
isEnabled = false
onBackPressedDispatcher.onBackPressed()
}
}
OnBackPressedDispatcher 객체에 OnBackPressedCallback 객체 등록하기
이제 앞서 만든 OnBackPressedCallback 객체를 OnBackPressedDispatcher 객체에 등록해보자. 등록하려면 다음과 같이 addCallback 함수를 사용하고 첫째 인자로 LifecycleOwner(Activity 혹은 Fragment)를 둘 째 인자로는 앞서 만든 onBackPressedCallback 객체를 넣으면 된다.
class MainActivity : ComponentActivity() {
private var lastBackPressedTime = 0L
private val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (lastBackPressedTime > System.currentTimeMillis() - 2000) {
finish()
} else {
Toast.makeText(this@MainActivity, "앱을 종료하려면 뒤로 가기를 한 번 더 눌려주세요", Toast.LENGTH_SHORT).show()
lastBackPressedTime = System.currentTimeMillis()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
...
}
}
자 이제 뒤로 가기 동작 설정이 완성되었다.
완성 화면
완성 화면은 다음과 같다. 두 번 연속으로 눌렀을 때만 앱이 종료되는 것을 볼 수 있다.