첫 프로젝트를 할 때는 사실 아무것도 몰랐기에, 스택 관리를 별로 신경쓰지 않았다. 하지만 무작정 쌓기만 하다 보니 화면을 여러 번 이동한 뒤 뒤로가기 할 때마다 계속해서 이전 화면들이 보이는 문제가 있었다. 스택 관리에 힘써야하는 이유이다.
화면 이동할 때 쌓여있는 모든 Activity, Fragment의 스택을 없애야 할 때가 있다. 이를테면 로그아웃 후 로그인 화면으로 돌입해야하는 상황처럼 말이다. 나는 처음에 무작정 쌓기만 하고, 이를 없애는 방법을 알지 못했다! 그래서 각각의 경우를 오늘 정리해보려고 한다.
👇🏻 화면 이동 시의 데이터 전달에 대해 더 알고 싶다면?
[Android/Kotlin] 화면을 이동할 때 데이터를 전달하는 방법 총정리
만약, A 액티비티
-> B 액티비티
로
startActivity(Intent(this, B_Activity::class.java))
식으로 이동했다면, 반대로 B 액티비티
-> A 액티비티
로 돌아오고 싶다면
finish()
만 써주면 된다.
하지만, A 액티비티
-> B 액티비티
로 이동하기 전에 이미 다른 액티비티가 쌓여 있는 상황이라면, 그리고 이를 종료하면서 한 번에 새로운 C 액티비티
로 가고 싶다면,
startActivity(Intent(this, C_Activity::class.java))
finishAffinity()
를 쓰면 된다.
이렇게 하면 이미 쌓여있던 액티비티들을 모두 종료하면서 C 액티비티
로 이동할 수 있다.
프래그먼트의 경우, 앞선 Activity보다는 조금 더 복잡할 수 있다.
같은 Activity 내의 Fragment일 경우에는
requireActivity().supportFragmentManager.beginTransaction()
.add(R.id.login_setting_frm, AlertLoginFragment())
.commitAllowingStateLoss()
- 참고) Activity 내에서 Fragment를 교체할 때는, 위와 비슷하지만
supportFragmentManager.beginTransaction() .replace(R.id.main_frm, Fragment_Name()) .commitAllowingStateLoss()
처럼,
requireActivity()
가 없어도 된다.
startActivity(Intent(requireActivity(), Activity_Name::class.java))
- 참고) Activity 내에서 Fragment를 바꿀 때는
위에서 Activity -> Activity에서startActivity(Intent(this, C_Activity::class.java))
처럼
this
를 썼던 것과 달리, Fragment에서는this
대신requireActivity()
를 써야한다.
를 쓴다.
A 액티비티
에서 이미 다른 B 액티비티 내의 B 프래그먼트
로 이동을 하며 스택이 쌓인 상황, 하지만 여기서 C 액티비티
로 이동하면서 모든 스택을 없애주어야 한다면, B 프래그먼트
에서 써야하는 코드는 다음과 같다.
activity?.finishAffinity()
startActivity(Intent(context, C_Activity()::class.java))
시작할 때 말한 로그아웃의 경우가 바로 이 경우였다.
MainActivity의 MyFragment에서 -> 로그아웃 버튼이 있는 MyBaseActivity의 MySettingFragment로 이동을 한 상황에서, 위의 코드를 써주면서 모든 스택을 지우고 로그인 화면으로 넘어갈 수 있었다.
그리고, B 액티비티 내의 B 프래그먼트
에서 B 액티비티를 종료하면서 A 액티비티
로 돌아가야하는 상황도 생겼는데,
그냥 단순한 Fragment -> Activity 화면 이동이었다면 startActivity(Intent(requireActivity(), A_Activity::class.java))
를 썼겠지만,
이 경우 내가 있는 액티비티를 종료하면서 다시 원래 있던 액티비티로 돌아가야 했기에 다른 방법이 필요했다. 이 경우 B 프래그먼트
에서 쓸 수 있는 코드는
Intent(requireActivity(), MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
}.also {
startActivity(it)
}
activity?.finishAffinity()
이것이다!
앞의 경우와는 달리 코드를 이렇게 쓰는 이유는 이미 A 액티비티
는 스택에 쌓여있는 상황인데, 앞의 경우처럼 finishAffinity()
후 바로 A 액티비티
로 화면을 이동하면 에러가 나기 때문이다.
로그아웃의 경우에는 완전 새로운 C 액티비티
(로그인) 화면으로 이동했기 때문에 이 에러가 발생하지 않는다.
사실 프래그먼트와 액티비티가 계속 정신없게 나와서!
조금 헷갈릴 것 같지만 누구에겐가는 도움이 될거라 믿는다. 내가 처음에는 많이 헤맸듯이!