Android Fragment 활용2

안녕하세요. 꿀발자입니다. 지난 포스팅에서 Android Fragment의 생명주기와 장단점을 다뤘는데요. 이번 글에서는 프래그먼트 간 데이터 전송, 상태 저장, 프래그먼트 전환, 그리고 ViewModelStoreOwnerLiveData를 활용한 데이터 관리 방법까지 심도 있게 살펴보겠습니다. 프래그먼트는 안드로이드 앱 개발에서 중요한 구성 요소로, 이러한 기술들을 이해하면 더 나은 사용자 경험과 앱의 안정성을 보장할 수 있습니다. 그럼 시작해볼까요?

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));

ViewModelLiveData 활용

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를 활용하세요.
  • 백스택을 적절히 사용하여 프래그먼트 상태를 관리하세요.

이러한 기법을 적절히 활용하면 동적이고 안정적인 프래그먼트 전환을 구현할 수 있습니다.

Leave a Comment