안녕하세요. 꿀발자입니다. 지난 포스팅에서 Android Fragment의 생명주기와 장단점을 다뤘는데요. 이번 글에서는 프래그먼트 간 데이터 전송, 상태 저장, 프래그먼트 전환, 그리고 ViewModelStoreOwner와 LiveData를 활용한 데이터 관리 방법까지 심도 있게 살펴보겠습니다. 프래그먼트는 안드로이드 앱 개발에서 중요한 구성 요소로, 이러한 기술들을 이해하면 더 나은 사용자 경험과 앱의 안정성을 보장할 수 있습니다. 그럼 시작해볼까요?
Android Fragment 데이터 전송과 상태 저장
프래그먼트 간 데이터 전송과 상태 저장은 안드로이드 개발에서 매우 중요한 작업입니다. 먼저 Bundle을 사용한 기본적인 데이터 전달 방법과 상태 저장을 살펴보겠습니다.
Fragment Bundle 데이터 전송
프래그먼트는 setArguments()
와 getArguments()
를 통해 데이터를 전달받을 수 있습니다. 이 방법은 데이터 전달이 간단하고 직관적입니다.
public class DataFragment extends Fragment { public static DataFragment newInstance(String data) { DataFragment fragment = new DataFragment(); Bundle args = new Bundle(); args.putString("key", data); fragment.setArguments(args); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_data, container, false); String data = getArguments() != null ? getArguments().getString("key", "default") : "default"; TextView textView = view.findViewById(R.id.textView); textView.setText(data); return view; } }
Fragment 상태 저장의 필요성
프래그먼트를 전환하거나 화면이 회전하면 기존 프래그먼트는 파괴되고 새로운 프래그먼트가 생성됩니다. 이 과정에서 기존 데이터나 UI 상태가 사라지는 문제가 발생할 수 있습니다. 상태를 저장하지 않으면 다음과 같은 문제를 겪을 수 있습니다.
- 입력 중인 폼 데이터 손실
- 선택한 항목이나 스크롤 위치 초기화
- 사용자 경험 저하
이를 해결하기 위해 onSaveInstanceState() 메서드를 활용하여 상태를 저장하고 복원할 수 있습니다.
onSaveInstanceState()를 활용한 상태 저장
onSaveInstanceState()는 프래그먼트가 파괴되기 전에 호출되어 상태를 저장하는 역할을 합니다. 이 메서드에서 상태 데이터를 저장한 뒤, onCreate() 또는 onViewCreated()에서 복원합니다. 화면 회전이나 메모리 부족으로 프래그먼트가 소멸되었다가 다시 생성될 때, 상태를 유지하려면 상태 저장(onSaveInstanceState)
,상태 복원(onViewCreated)을 사용해야 합니다.
@Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putString("input_data", editText.getText().toString()); // 데이터 저장 } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); if (savedInstanceState != null) { editText.setText(savedInstanceState.getString("input_data")); // 데이터 복 } }
Android Fragment 전환과 백스택 관리
프래그먼트 전환(Fragment Transaction)은 한 액티비티 내에서 동적으로 프래그먼트를 교체하거나 추가, 제거하는 작업입니다. 예를 들어, 탭을 선택하거나 버튼 클릭 시 새로운 프래그먼트로 화면을 변경하는 경우가 이에 해당합니다.
FragmentTransaction으로 화면 전환
프래그먼트를 전환할 때 FragmentTransaction을 사용하며, 기본적으로 다음과 같은 메서드들이 사용됩니다.
- replace(): 기존 프래그먼트를 새 프래그먼트로 교체.
- add(): 현재 프래그먼트 위에 새 프래그먼트를 추가.
- remove(): 특정 프래그먼트를 제거.
- addToBackStack(): 이전 프래그먼트 상태를 백스택에 추가.
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, new AnotherFragment()); transaction.addToBackStack(null); transaction.commit();
FragmentTransaction의 addToBackStack() 메서드를 사용하면 백스택에 저장된 프래그먼트로 쉽게 돌아갈 수 있습니다.
transaction.addToBackStack("example_fragment"); transaction.commit();
addToBackStack()에 추가된 프래그먼트는 상태가 유지된 채로 복원됩니다.
ViewModel 활용
ViewModel은 프래그먼트 생명주기와 독립적으로 동작하기 때문에, 화면 전환 시 데이터가 손실되지 않습니다. ViewModel은 다음과 같이 사용할 수 있습니다.
public class MyViewModel extends ViewModel { private MutableLiveData<String> userInput = new MutableLiveData<>(); public MutableLiveData<String> getUserInput() { return userInput; } }
프래그먼트에서는 ViewModel을 연결하여 데이터를 관리합니다.
MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class); viewModel.getUserInput().observe(getViewLifecycleOwner(), input -> editText.setText(input));
ViewModel과 LiveData 활용
ViewModel과 LiveData를 활용하면 상태 관리가 훨씬 수월해집니다. 특히 화면 전환이나 프래그먼트 재생성 시 데이터 손실을 방지할 수 있습니다.
public class SharedViewModel extends ViewModel { private final MutableLiveData<String> sharedData = new MutableLiveData<>(); public LiveData<String> getSharedData() { return sharedData; } public void setSharedData(String data) { sharedData.setValue(data); } }
LiveData를 통해 데이터 변경을 관찰하고 UI를 자동으로 업데이트할 수 있습니다.
SharedViewModel viewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); viewModel.getSharedData().observe(getViewLifecycleOwner(), data -> { textView.setText(data); });
ViewModelStoreOwner 활용
프래그먼트와 ViewModel을 더 효율적으로 활용하기 위해 ViewModelStoreOwner 개념을 이해하는 것이 중요합니다. ViewModelStoreOwner는 ViewModel의 생명주기를 관리하는 역할을 하며, 데이터를 중앙에서 관리하거나 여러 프래그먼트 간 공유할 수 있게 합니다.
ViewModelStoreOwner란?
- ViewModelStoreOwner는 ViewModel의 저장소를 관리하는 인터페이스로,
Activity
,Fragment
,NavHostFragment
등이 이 역할을 수행합니다. - 이를 통해 같은 Activity나 NavHostFragment 하위의 프래그먼트들이 동일한 ViewModel을 공유 할 수 있습니다.
ViewModelStoreOwner 활용 예제
Activity와 프래그먼트 간 데이터 공유
public class SharedViewModel extends ViewModel { private final MutableLiveData<String> sharedData = new MutableLiveData<>(); public LiveData<String> getSharedData() { return sharedData; } public void setSharedData(String data) { sharedData.setValue(data); } }
requireActivity()
를 사용해 Activity 수준에서 ViewModel을 가져옵니다.
public class FragmentA extends Fragment { private SharedViewModel viewModel; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); viewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); viewModel.getSharedData().observe(getViewLifecycleOwner(), data -> { textView.setText(data); }); button.setOnClickListener(v -> { viewModel.setSharedData("Data from Fragment A"); }); } }
NavHostFragment와 ViewModel
Navigation 구성 요소를 사용할 때, NavHostFragment를 ViewModelStoreOwner로 활용하면 더욱 편리합니다.
implementation "androidx.navigation:navigation-fragment-ktx:2.5.0" implementation "androidx.navigation:navigation-ui-ktx:2.5.0"
SharedViewModel viewModel = new ViewModelProvider( NavHostFragment.findNavController(this).getViewModelStoreOwner(R.id.nav_graph) ).get(SharedViewModel.class);
이 방식은 여러 프래그먼트가 같은 ViewModel을 공유해야 하는 상황에서 유용합니다. https://honey-dev.com/firebase-개념과-활용/
Final Thoughts
이번 글에서는 프래그먼트 간 데이터 전송, 상태 저장, 프래그먼트 전환, 그리고 ViewModelStoreOwner와 LiveData를 활용한 데이터 관리 방법까지 심도 있게 살펴보았습니다. 이러한 기술들은 복잡한 UI를 다루는 현대 안드로이드 앱 개발에서 필수적이며, 프래그먼트와 함께 사용할 때 앱의 안정성과 사용자 경험을 크게 향상시킬 수 있습니다. Bundle과 ViewModel, LiveData 등을 적절히 조합하여 더욱 안정적이고 효율적인 앱을 개발해 보세요. 프래그먼트 전환과 상태 저장은 사용자 경험을 개선하고 앱의 안정성을 높이는 중요한 작업입니다.
- 간단한 데이터는 onSaveInstanceState()를 사용해 저장하고 복원하세요.
- 복잡한 상태 관리가 필요하다면 ViewModel과 LiveData를 활용하세요.
- 백스택을 적절히 사용하여 프래그먼트 상태를 관리하세요.
이러한 기법을 적절히 활용하면 동적이고 안정적인 프래그먼트 전환을 구현할 수 있습니다.