프래그먼트의 데이터 전달

낄낄몬스터·2024년 7월 19일
0

앱 개발 숙련

목록 보기
5/9
post-custom-banner

Activity → Fragment

액티비티에서 프래그먼트로 데이터를 전달할 때는, 프래그먼트의 인스턴스를 생성하고 newInstance 메소드를 통해 데이터를 전달함. Bundle 객체를 사용하여 데이터를 프래그먼트의 인자(arguments)로 설정하고, 이 인자를 프래그먼트가 받아 사용함

MainActivity.kt (보내는 코드)

Fragment1Btn 클릭 리스너 안에서 FirstFragment의 인스턴스를 생성하고, newInstance 메소드에 데이터를 전달하여 프래그먼트를 설정(set). Fragment2Btn에 대해서도 동일한 방법으로 SecondFragment에 데이터를 전달

binding.run {
            fragment1Btn.setOnClickListener{
                // [1] Activity -> FirstFragment
                val dataToSend = "Hello First Fragment! \n From Activity"
                val fragment = FirstFragment.newInstance(dataToSend)
                setFragment(fragment)
            }

            fragment2Btn.setOnClickListener {
                // [1] Activity -> SecondFragment
                val dataToSend = "Hello Second Fragment!\n From Activity"
                val fragment = SecondFragment.newInstance(dataToSend)
                setFragment(fragment)
            }

FirstFragment.kt (받는 코드)

newInstance 메소드에서 전달받은 데이터를 Bundle에 담고, 프래그먼트의 인자로 설정. onViewCreated에서는 인자로 받은 데이터를 텍스트 뷰에 설정

private var param1: String? = null

companion object {
        @JvmStatic
        fun newInstance(param1: String) =
            // [1] Activity -> FirstFragment
            FirstFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                }
            }
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // [1] Activity -> FirstFragment
        binding.tvFrag1Text.text = param1     
}

실행화면

Fragment → Fragment

한 프래그먼트에서 다른 프래그먼트로 데이터를 전달할 때는, 첫 번째 프래그먼트에서 두 번째 프래그먼트의 newInstance 메소드를 사용하여 인스턴스를 생성하고, 데이터를 전달

FirstFragment.kt (보내는 코드)

버튼 클릭 시 SecondFragment의 새 인스턴스를 생성하고, newInstance 메소드를 사용하여 데이터를 전달한 후 프래그먼트 트랜잭션을 통해 두 번째 프래그먼트를 시작

// [2] Fragment -> Fragment
        binding.btnGofrag2.setOnClickListener{
            val dataToSend = "Hello Fragment2! \n From Fragment1"
            val fragment2 = SecondFragment.newInstance(dataToSend)
            requireActivity().supportFragmentManager.beginTransaction()
                .replace(R.id.frameLayout, fragment2)
                .addToBackStack(null)
                .commit()
        }

SecondFragment.kt (받는 코드)

newInstance 메소드로 전달받은 데이터를 Bundle에 담고, onCreate 또는 onViewCreated에서 Bundle로부터 데이터를 추출하여 사용

private const val ARG_PARAM1 = "param1"

class SecondFragment : Fragment() {

    private var param1: String? = null

    private var _binding: FragmentSecondBinding? = null
    private val binding get() = _binding!!


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentSecondBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // [2] Fragment -> Fragment
        binding.tvFrag2Text.text = param1
    }


    companion object {
        @JvmStatic
        fun newInstance(param1: String) =
            // [1] Activity -> FirstFragment
            SecondFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                }
            }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        // Binding 객체 해제
        _binding = null
    }
}

실행화면

Fragment → Activity

프래그먼트에서 액티비티로 데이터를 전달할 때는 콜백 인터페이스를 정의하고, 해당 인터페이스를 액티비티가 구현하도록 함. 프래그먼트는 이 인터페이스를 사용하여 액티비티에 데이터를 전달

SecondFragment.kt (보내는 코드)

FragmentDataListener 인터페이스를 정의하고, 프래그먼트가 액티비티에 붙을 때 (onAttach) 액티비티가 이 인터페이스를 구현했는지 확인. 버튼 클릭 리스너에서 onDataReceived 메소드를 호출하여 데이터를 액티비티에 전달

private const val ARG_PARAM1 = "param1"

interface FragmentDataListener {
    fun onDataReceived(data: String)
}

class SecondFragment : Fragment() {

    // [3] SecondFragment -> Activity
    private var listener: FragmentDataListener? = null

    private var param1: String? = null

    private var _binding: FragmentSecondBinding? = null
    private val binding get() = _binding!!


    override fun onAttach(context: Context) {
        super.onAttach(context)

        // [3] SecondFragment -> Activity
        if (context is FragmentDataListener) {
            listener = context
        } else {
            throw RuntimeException("$context must implement FragmentDataListener")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentSecondBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // [2] Fragment -> Fragment
        binding.tvFrag2Text.text = param1

        // [3] SecondFragment -> Activity
        binding.btnSendActivity.setOnClickListener{
            val dataToSend = "Hello from SecondFragment!"
            listener?.onDataReceived(dataToSend)
        }
    }


    companion object {
        @JvmStatic
        fun newInstance(param1: String) =
            // [1] Activity -> FirstFragment
            SecondFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                }
            }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        // Binding 객체 해제
        _binding = null
        listener = null
    }
}

MainActivity.kt (받는 코드)

MainActivity는 FragmentDataListener 인터페이스를 구현하고, onDataReceived 메소드를 오버라이드하여 프래그먼트로부터 데이터를 받음. 데이터를 받으면 Toast 메시지로 표시

class MainActivity : AppCompatActivity(), FragmentDataListener {

    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

					binding.apply {
				    fragment1Btn.setOnClickListener{
			        // [1] Activity -> FirstFragment
			        val dataToSend = "Hello First Fragment! \n From Activity"
			        val fragment = FirstFragment.newInstance(dataToSend)
			        setFragment(fragment)
				    }

				    fragment2Btn.setOnClickListener {
			        // [1] Activity -> SecondFragment
			        val dataToSend = "Hello Second Fragment!\n From Activity"
				      val fragment = SecondFragment.newInstance(dataToSend)
			        setFragment(fragment)
				    }
					}


        setFragment(FirstFragment())
    }

    private fun setFragment(frag : Fragment) {
        supportFragmentManager.commit {
            replace(R.id.frameLayout, frag)
            setReorderingAllowed(true)
            addToBackStack("")
        }
    }

    // [3] SecondFragment -> Activity
    override fun onDataReceived(data: String) {
        // Fragment에서 받은 데이터를 처리
        Toast.makeText(this, data, Toast.LENGTH_SHORT).show()
    }
}

실행화면

profile
음악을 사랑하는 예비 앱개발자
post-custom-banner

0개의 댓글