Android 애플리케이션에서 Fragment 전환을 구현할 때 많은 개발자들이 replace() 메서드를 사용한다. 하지만 이 방식에는 심각한 성능 문제가 있다. 매번 전환할 때마다 Fragment가 새로 인스턴스화되고 데이터가 다시 로드되기 때문에, 성능과 사용자 데이터 사용량 측면에서 비효율적이다.
replace() 메서드의 문제점
Android 공식 문서에 따르면, replace() 메서드는 더 이상 필요 없는 Fragment를 교체할 때만 사용하는 것이 바람직하다.、日常적인 Fragment 전환에는 적합하지 않은 방식이다.
올바른 전환 방법: add(), hide(), show() 활용
효율적인 Fragment 전환을 위해서는 다음 패턴을 사용해야 한다:
- 초기 Fragment 추가 시
add()사용 - 다른 Fragment로 전환 시 현재 Fragment는
hide(), 새 Fragment는add() - 이미 추가된 Fragment 간 전환 시
hide()와show()만 사용
이렇게 하면 여러 Fragment를 전환할 때마다 다시 인스턴스화하지 않아도 된다.
/**
* Fragment 전환 관리자
*
* @param current 현재 표시 중인 Fragment
* @param target 전환할 목표 Fragment
* @param containerId ViewGroup 컨테이너 ID
*/
public void switchFragment(Fragment current, Fragment target, int containerId) {
if (activeFragment != target) {
activeFragment = target;
FragmentTransaction transaction = fragmentManager.beginTransaction();
if (!target.isAdded()) {
transaction.hide(current)
.add(containerId, target, target.getClass().getSimpleName())
.commit();
} else {
transaction.hide(current).show(target).commit();
}
}
}
메모리 부족 시 발생하는 Fragment 중복 문제
위와 같이 구현하면 성능 문제는 해결되지만, 저사양 기기에서 메모리 부족으로 Activity가 재생성될 때 Fragment가 중복해서 표시되는 문제가 발생할 수 있다. 이는 Activity가回收되어 다시 시작될 때 Fragment가 중복으로 생성되기 때문이다.
savedInstanceState 검증을 통한 문제 해결
Activity의 onCreate() 메서드에서 savedInstanceState 여부를 반드시 확인해야 한다. 이 값을 검사함으로써 시스템이 Activity를 재구축하는 경우인지, 처음 시작하는 경우인지 구분할 수 있다.
Fragment를 찾을 때는 tag 파라미터가 필수적이다. 하나의 ViewGroup에 여러 Fragment가 추가될 수 있으므로, 각 Fragment를 고유하게 식별하기 위해 tag를 사용해야 한다.
/**
* Activity 상태 복원 검증
* 메모리 부족 상황에서 Fragment 중복 방지
*
* @param savedInstanceState 번들 상태
*/
private void restoreFragmentState(Bundle savedInstanceState) {
if (savedInstanceState == null) {
fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
HomeFragment home = new HomeFragment();
activeFragment = home;
transaction.add(R.id.fragment_container, home, TAG_HOME);
transaction.commit();
} else {
HomeFragment home = (HomeFragment) fragmentManager
.findFragmentByTag(TAG_HOME);
ProfileFragment profile = (ProfileFragment) fragmentManager
.findFragmentByTag(TAG_PROFILE);
SettingsFragment settings = (SettingsFragment) fragmentManager
.findFragmentByTag(TAG_SETTINGS);
fragmentManager.beginTransaction()
.show(home)
.hide(profile)
.hide(settings)
.commit();
activeFragment = home;
}
}
핵심 정리
Fragment 전환 시 반드시 기억해야 할 점은 다음과 같다:
replace()대신add(),hide(),show()조합 사용- Fragment 추가 시 고유한 tag 지정
- Activity
onCreate()에서savedInstanceStatenull 검사 수행 - Activity 재구축 시 기존 Fragment를 tag로 찾아서 상태 복원
이 방법들을 적용하면 Fragment 전환 성능을 크게 개선하면서도 시스템 메모리 관리에 따른 중복 표시 문제를 원천적으로 방지할 수 있다.