본문 바로가기

Android

[Android] Fragment간 데이터 공유(Navigation, SafeArgs)

Fragment간에 데이터를 공유하는 몇 가지 방법에 대해 적어보고자 한다.

 

물론 틀린 부분이 있을 수도 있다💦

 

 

1. Bundle()

 

fragment의 데이터 전달은 많은 사람들이 bundle을 사용해서 처리해왔다.


사용 방법은 다음과 같다.

 

val testFragment = TestFragment()
val bundle = Bundle()
bundle.putString("id", et_id.text.toString())

testFragment.arguments = bundle
parentFragmentManager.beginTransaction)
        .replace(R.id.fragment_container, testFragment())
        .commit()

//ReceiveFragment
var restult = arguments?.getString("id")

 

 

2. Navigation SafeArgs


JetPack 라이브러리중 Navigation을 이용하면 복잡한 Fragment의 이동과 데이터 전달을 가시적이고 효율적으로 작성할 수 있다.

 

2021.03.10 - [Android] - Navigation으로 Fragment를 전환시켜보자!

 

Navigation으로 Fragment를 전환시켜보자!

Navigation In JetPack 보통 Activity의 전환은 Intent, Fragment의 전환은 transaction을 사용했다. Jetpack 라이브러리 내의 Navigation을 이용하면 프래그먼트간의 전환을 구현할 수 있다. 1. dependency 추가..

peaceful-coding-diary.tistory.com


navigation_graph를 통해 Fragment간의 Action과 Data 전달을 정의할 수 있다.

<fragment

    android:id="@+id/homeFragment"

    android:name="com.example.lecturesopt28th.home.view.HomeFragment"

    android:label="fragment_home"

    tools:layout="@layout/fragment_home" >

    <argument

        android:name="id"

        app:argType="string" />

    <action

        android:id="@+id/action_homeFragment_to_repositoryFragment"

        app:destination="@id/repositoryFragment" />

</fragment>

 

위와 같이 Fragment에 전달받고 싶은 데이터 형식을 argument로 선언해놓고

 

해당 Fragment로 전화할 때 형식에 맞는 데이터를 보내주면 된다.

 

데이터를 수신할 때는 by navArgs() 속성 위임을 사용하여 argument에 액세스할 수 있다.

 

///Pass Data
private fun login() {
    binding.buttonLogin.setOnClickListener {
        if(checkInputText()) {
            Toast.makeText(requireContext(), "Please input email or password", Toast.LENGTH_SHORT).show()
        } else {
            val action =
                LogInFragmentDirections.actionLogInFragmentToHomeFragment(viewModel.id.value!!)
            Navigation.findNavController(binding.root).navigate(action)
        }
    }
}

//Receive Data
private  val args:  HomeFragmentArgs by navArgs()
viewModel.userId.value = args.id 

 

3. ViewModel을 이용한 데이터 공유

 

같은 부모를 가진 Fragment에서는 ViewModel을 이용하면 데이터를 공유하기 수월하다.

 

하나의 Activity에 여러 Child Fragment들이 존재하면 ActivityViewModel을 이용하여 Fragment간에 데이터를 공유할 수 있다.

 

이 방법이 편리하긴 하지만 같은 자원을 공유한다는 것은 그만큼 결합도가 높아진다는 것이기 때문에 설계를 잘해야한다.

 

private val viewModel by activityViewModels<SharedViewModel>()

or

private val viewModel: SharedViewModel by activiyViewModels()

 

그렇다면 ParentFragment 하위에 여러 개의 ChildeFragment가 있다면 어떻게 해야할까?


여기서도 ActivityViewModel을 만들어 공유할 수 있지만, 이 방식으로 한다면 ParentFragment가 소멸되어도 ViewModel은 살아있어 버리기 때문에 적합하지 않다.

 

하지만 똑같은 방식으로 이렇게 사용하면 된다.

 

//Parent Fragment
private val viewModel by viewModels()

//Child Fragment
private val viewModel by viewModels(ownerProducer = {requireParentFragment().requireParentFragment()})