안드로이드 스튜디오 Fragment 화면 전환 시 상태 유지(With Kotlin)

Purang·2022년 10월 8일
1

Android Studio

목록 보기
17/28

Fragment 사용할 때 화면 전환을 사용하게 되는데 이 때 화면 전환 시 fragment의 재생성으로 인해 데이터가 사라지는 현상이 발생하게 되었습니다.
이를 방지하기 위해 상태 유지하기 위한 공부를 하게 되었습니다.

<LinearLayout
        android:id="@+id/main_content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical"
        />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:menu="@menu/bottom_menu"/>

저의 xml입니다. LinearLayout은 메인 컨텐츠 화면을 나타내는 곳입니다.

그리고 메인 액티비티 코드입니다.

class MainActivity : AppCompatActivity() {
    private lateinit var mBinding : ActivityMainBinding
    private lateinit var main_content : LinearLayout //xml의 content를 담는 layout
    private lateinit var bottom_navigationview : BottomNavigationView
    
    //Tag로 각 fragment를 구별합니다.
    private val TAG_HOME = "home_fragment"
    private val TAG_BLANK = "blank_fragment"
    private val TAG_ACCOUNT = "account_fragment"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = ActivityMainBinding.inflate(layoutInflater)
        val view = mBinding.root
        setContentView(view)
		
        
        //처음 시작 화면을 homeFragment로 설정(add로 생성 replace x)
        setFragment(TAG_HOME, HomeFragment())

        initBottomNavigationBar()
    }
	
    //bottomnavigation 초기화 세팅
    private fun initBottomNavigationBar() {
        main_content = findViewById(R.id.main_content)
        bottom_navigationview = findViewById(R.id.bottomNavigationView)
		
        //
        mBinding.bottomNavigationView.setOnItemSelectedListener { item->
            when(item.itemId){
                R.id.home -> setFragment(TAG_HOME, HomeFragment())
                R.id.contemplating -> setFragment(TAG_BLANK, BlankFragment())
                R.id.account -> setFragment(TAG_ACCOUNT, AccountFragment())
            }
            true
        }
    }
	
    
    //fragment 상태 유지를 위한 컨트롤 함수
    fun setFragment(tag : String, fragment: Fragment) {
        val manager : FragmentManager = supportFragmentManager
        val bt = manager.beginTransaction()
			
        //바텀 네비게이션의 tag(즉, 메뉴)가 선택 되었을 때 생성되있지 않을 경우
        //바로 생성(add) 해줍니다.
        if (manager.findFragmentByTag(tag) == null) {
            bt.add(R.id.main_content, fragment, tag)
        }
		
        //코드 작성에 용이하게 따로 변수로 할당
        val home = manager.findFragmentByTag(TAG_HOME)
        val blank = manager.findFragmentByTag(TAG_BLANK)
        val account = manager.findFragmentByTag(TAG_ACCOUNT)
			
        //위에서 생성한 fragment들을 
        //우선 전부 hide 시킨 후
        if (home != null) {
            bt.hide(home)
        }
        if (blank != null) {
            bt.hide(blank)
        }
        if (account != null) {
            bt.hide(account)
        }
		
        //tag로 입력받은 fragment만 show를 통해 보여주도록 합니다.
        if (tag == TAG_HOME) {
            if (home != null) {
                bt.show(home)
            }
        }
        else if (tag == TAG_BLANK) {
            if (blank != null) {
                bt.show(blank)
            }
        }
        else if (tag == TAG_ACCOUNT) {
            if (account != null) {
                bt.show(account)
            }
        }
        bt.commitAllowingStateLoss()
    }

}

commit은 activity가 state save 하기 전에 이루어져야 합니다. 그러나 state save 후에 commit이 호출된다면 예외 에러가 발생합니다. 만약 state save 와 관계없이 그리고 fragement 의 state 저장과 관련없게 작동하게 하려면 commit 대신 commitAllowingStateLoss() 를 호출해줘야 합니다.
출처:블로그

위 처럼 코드 작성 시 fragment의 상태(데이터, 위치 등)이 유지 되는 것을 확인할 수 있습니다.

참조 - [Android Kotlin] 안드로이드 코틀린 Fragment 상태 유지
fragment 상태 유지

profile
몰입의 즐거움

2개의 댓글

comment-user-thumbnail
2024년 5월 7일

먼저 숨겨버린 다음에, show하는 것 전부 좋은 방법이네요! 감사합니다 ^^

1개의 답글