FrameLayout에서 Fragment 올바르게 사용하기
DoDoBest
·2024. 5. 2. 16:05
FrameLayout에서 Fragment를 사용하는 방법
안드로이드 공식 문서에서 Fragment를 위한 container로 FragmentContainerView 사용을 강력하게 권장합니다.
It is strongly recommended to always use a FragmentContainerView as the container for fragments, as FragmentContainerView includes fixes specific to fragments that other view groups such as FrameLayout do not provide.
https://developer.android.com/guide/fragments/create#add
그럼에도 FrameLayout에서 Fragment를 사용해봅시다. FrameLayout은 FragmentContainerView에서 제공하는 name attribute를 제공하지 않습니다. 그래서 코드에서 Fragment를 지정해줘야 합니다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
supportFragmentManager.beginTransaction()
.add(R.id.frame_layout, SearchFragment())
.commit()
}
}
위 코드는 어떤 문제가 있을까요? Configuration Change가 발생할 때마다, 화면에 있는 SearchFragment가 다시 복원되고 새로운 SearchFragment가 FrameLayout에 추가되어, 여러 SearchFragment가 중첩되어 보이게 됩니다.
아래 GIF는 소프트웨어 키보드로 감자를 입력한 후, 블루투스 키보드를 연결하고 고구마를 입력한 결과입니다.
블루투스 키보드를 연결하면 Android Manifest에서 별도로 설정하지 않는한 Configuration Change가 발생합니다.
Layout Inspector로 확인해보면 FrameLayout에 SearchFragment가 Configuration Change 횟수만큼 추가로 생성된 것을 확인할 수 있습니다.
기존 Fragment는 어떻게 복원된 걸까요?
화면에 존재하는 Fragment가 복원되는 방법
Configuration change가 발생하면 Activity가 파괴되고 재생성됩니다. 파괴되는 시점에 화면에 존재하는 Fragment는 savedInstanceState에 저장됩니다. Activity가 다시 생성되면 전달된 savedInstanceState를 이용해 Fragment가 복원됩니다. 직접 복원하는 코드를 작성할 필요 없이 자동으로 복원됩니다.
그래서 Configuration Change가 발생하면 기존의 Fragment가 복원되고, Transaction add 함수를 통해 새로운 Fragment가 FrameLayout에 추가되었던 것입니다.
올바른 사용방법
그래서 FrameLayout 최초로 보여줄 Fragment를 설정하는 코드는 savedInstanceState가 null인 경우에만 추가해줍니다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.add(R.id.frame_layout, SearchFragment())
.commit()
}
}
}
Fragment에 초기 값이 필요하다면 add args에 bundle 형태로 전달해줄 수 있습니다.
val bundle = bundleOf("query" to "Android")
supportFragmentManager.beginTransaction()
.add(R.id.frame_layout, SearchFragment::class.java, bundle)
.commit()
오해한 개념
Fragment는 FragmentTransaction의 addToBackStack 함수로 backstack에 저장한 경우에만 복원된다고 생각했습니다.
참고 자료
https://developer.android.com/guide/fragments/create
https://developer.android.com/guide/fragments/fragmentmanager#perform
'학습' 카테고리의 다른 글
Fragment에서 뒤로가기 동작 커스텀하기 (0) | 2024.05.04 |
---|---|
EditText에서 하드웨어 키보드 대응하기 with 가상 키보드, 커서 (1) | 2024.05.02 |
Fragment에서 ViewPager2 + TabLayout 사용하기 (0) | 2024.04.24 |
직렬화란 무엇이고, 왜 필요하며, 어떻게 직렬화를 할 수 있을까? (0) | 2024.04.18 |
Android Task와 ACTIVITY FLAG 정복하기 (0) | 2024.04.07 |