본문 바로가기
Mobile App/Android

[안드로이드] Fragment replace 이전 Fragment 버튼 리스너 동작 이슈

by Jman 2023. 9. 25.
Fragment 간 이동 할 때 add, replace, remove, addToBackStack 등
다양한 방법으로 Fragment 를 다룰 수 있다.


내가 겪은 이슈는 A -> B 로 Fragment 를 이동할 시
replace 를 이용하면 기존 stack 에 쌓인 Fragment(A) 는 사라지고,
replace 로 대체되는 Fragment(B) 만 남아 있어야 한다.

하지만,
그렇지 않았다.

그래서 
Fragment(A) 에 있는 버튼 리스너 들이 Fragment(B) View 에서 눌리게 된다...

 

 

 

일단 나는 아래와 같이 코드를 작성해서, 범용적으로 Fragment 를 사용하려고 했다.

replace, add, remove, popBackStack

 

fun Activity?.moveFragment(fragment: Fragment) {
    this.isNotNull {
        (it as 액티비티명).supportFragmentManager.beginTransaction().replace(R.id.레이아웃명, fragment).commit()
    }
}

fun Activity?.popBackStack() {
    this.isNotNull {
        val fm = (it as 액티비티명).supportFragmentManager
        if (fm.backStackEntryCount > 0) {
            fm.popBackStack()
        }
    }
}

fun Activity?.removeFragment(fragment: Fragment) {
    this.isNotNull {
        (it as 액티비티명).supportFragmentManager.beginTransaction().remove(fragment).commit()
    }
}

fun Activity?.addFragment(fragment: Fragment) {
    this.isNotNull {
        (it as 액티비티명).supportFragmentManager.beginTransaction().add(R.id.레이아웃명, fragment).addToBackStack("").commit()
    }
}

 

 

이슈가 난 상황은 add 를 사용했다면 충분히 그럴 수 있다고 생각하는데?

그런데 replace 가 이러하니, 너무나 궁금해서 라이프사이클이 어떻게 동작하는지 로그를 한 번 찍어보았다.

 

이슈 상황

Fragment A -> Fragment B

첫 번째 A -> B (replace 적용 상황)

Fragment B -> Fragment A

첫 번째 A -> B -> A (replace 적용 상황)

 

정상적인 상황

Fragment A -> Fragment B

두 번째 A -> B (replace 적용 상황)

 

Fragment B > Fragment A

두 번째 A -> B -> A (replace 적용 상황)

 

A => MoreFragment

B => CouponTermsFragment

 

위 사진을 보면, Fragment A 가 사라지지 않은 것을 알 수 있다.

이것만 보면  Fragment B 에서 A의 버튼 리스너가 동작하는지는 알 수 있는데

이러면 안되는 거 아닌가?

replace 는 이전에 쌓인 Fragment 는 다 사라지게 아닌가? 왜 이렇게 되지?

 

웃긴건, 처음으로 A -> B 로 이동하면 이슈 상황처럼 라이프사이클이 움직여지고 

두 번째부턴 정상적인 상황 처럼 라이프사이클이 움직여진다.

이건, add 와 replace 둘 다 똑같은 현상이였다.

 

이유가 뭘까?

솔직히 정확한 이유를 찾지 못했다. 다만, 아래 글을 읽으면 조금 도움될 것이다.

https://stackoverflow.com/questions/11326155/fragment-onresume-onpause-is-not-called-on-backstack

 

Fragment onResume() & onPause() is not called on backstack

I have multiple fragment inside an activity. On a button click I am starting a new fragment, adding it to backstack. I naturally expected the onPause() method of current Fragment and onResume() of ...

stackoverflow.com

그렇지만 어떻게 해야할 지를 해결은 해야했으니 아래은 방법으로 해결했다.

 

어떻게 해야할까?

일단, 라이프사이클을 확인해보면,  생각했던대로 replace 가 되지 않는 걸 확인할 수 있다.

따라서 Fragment(A)  > Fragment(B) 로 이동할 시, add + addToBackStack 를 사용하였다.

 

addToBackStack 을 이용해서 기존 Host Activity Stack 에 Fragment 를 넣어서 BaskStack 했을 시, 이전 Fragment 가 나오도록 한다.

 

그런 다음에 A와 B Fragment root view 에 Clickable 속성을 true 값을 준다.

 

위와 같이하면, B Fragment 로 이동 후, A Fragment 버튼 리스너가 먹히지 않는 것을 확인할 수 있다.

 

다시 정리하면?

1. replace > add + addToBackStack 으로 변경

2. xml 상위 root view 에 clickable 속성에 true 값을 주기