본문 바로가기

개발 노트/Kotlin

[Android/Kotlin] Activity, Fragment간 데이터 주고받기

일단 아래와같이 MainActivity에 버튼 두개를 만들고, Frag1버튼을 누르면 FirstFragment로 이동, Frag2버튼 누르면 SecondFragment로 이동하도록 코드는 미리 짜놨고 여기서는 데이터를 전송하고 받는 부분만 작성해볼것이다

 

# Activity -> Fragment 데이터 전달 

newInsatance함수를 따로 만들어서 하는방법과

그냥 Bundle을 사용하여 데이터를 전달하는 방법 2가지를 사용해서 해볼것이다

 

기본적으로 저 버튼들이 MainActivtiy에 있는 버튼들이므로, 저 버튼을 클릭했을때 Fragment로 값을 전달하고, Fragment에서는 값을 받아와서 text로 뿌려주는 작업을 해볼것이다

 

 

1) newInsatance함수를 따로 만들어서 하는방법

 

# Activity에서 Fragment로 데이터 보내기

일단 dataToSend변수에 전달할 String값을 담아주고

FirstFragment로 이동할때 newInstance함수에 dataToSend값을 담아서 이동한다

class MainActivity : AppCompatActivity() {

    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 뷰바인딩 사용
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)


        binding.apply {
            // Activity -> Fragment로 데이터전달
            fragment1Btn.setOnClickListener{
                val dataToSend = "Activity -> Fragment\n로 데이터전달1"
                val fragment = FirstFragment.newInstance(dataToSend)
                setFragment(fragment)
            }


            fragment2Btn.setOnClickListener {
                setFragment(SecondFragment())
            }
        }

        // MainActivity실행되자마자 나타날 프레그먼트
        setFragment(FirstFragment())
    }

    private fun setFragment(fragment : Fragment) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.frameLayout, fragment)
            .commit()
    }




}

MainActivity.kt

 

FirstFragment에서 companion object로 newInstance함수를 만들어준다

param1에 MainActivtiy에서 전달한 데이터가 들어있을것이고, 그 데이터를 bundle을 사용해서 arguments에 저장해준다

companion object{
    fun newInstance(param1 : String) =
        FirstFragment().apply {
            // param1에 MainActivity에서 전달한 데이터가 들어있음
            // 얘를 arguments에 저장
            arguments = Bundle().apply {
                putString(ARG_PARAM1, param1)
            }
        }
}

FirstFragment.kt

 

# Fragment에서 데이터 받기

이제 MainActivity에서 보낸 데이터를 FirstFragment에서 받는 작업을 해볼것이다

const val을 사용해서 ARG_PARAM1이라는 변수를 설정해주고 (특정한 고정된 값을 사용하고 싶을 때 const val 사용)

param1이라는 변수를 null값으로 설정해준다

그리고 onCreate()에서 bundle을 사용해서 받아온 데이터를 param1에 넣어준다

그러면 param1에는 MainActivity에서 받아온 데이터가 들어있을것이다!

이제 onViewCreated()에서 text에 param1데이터를 연결해줘서 텍스트에 데이터를 뿌려준다

private const val ARG_PARAM1 = "param1"

class FirstFragment : Fragment() {

    private lateinit var binding: FragmentFirstBinding
    private var param1 : String? = null


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

        // MainActivity에서 보낸 데이터를 꺼내서 param1에 넣어줌
        // arguments가 null이 아닐때만 실행
        // arguments안에 bundle이라는 객체로 받아온데이터가 들어있는데
        arguments?.let {
            // param1에 bundle을 사용해서 받아온 데이터를 넣어줌
            param1 = it.getString(ARG_PARAM1)
        }


    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        binding = FragmentFirstBinding.inflate(inflater, container, false)


        return binding.root
    }


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // text와 받아온데이터인 param1을 연결
        binding.Fragment1.text = param1
    }


    companion object{
        fun newInstance(param1 : String) =
            FirstFragment().apply {
                // param1에 MainActivity에서 전달한 데이터가 들어있음
                // 얘를 arguments에 저장
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                }
            }
    }


}

FirstFragment.kt

 

 

2) Bundle을 사용하여 데이터를 전달하는 방법

 

# Activity에서 Fragment로 데이터 보내기

fragment2Btn을 눌렀을때 

bundle을 사용해서 key값과 value값을 넘겨준다(bundle은 맵형식과 비슷하게 key, value값의 쌍으로 이루어져있는 특징이 있음)

그리고 프래그먼트의 arguments를 통해 생성된 bundle을 할당해준다

class MainActivity : AppCompatActivity() {

    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 뷰바인딩 사용
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)


        binding.apply {
            // Activity -> Fragment로 데이터전달
            fragment1Btn.setOnClickListener{
                val dataToSend = "Activity -> Fragment\n로 데이터전달1"
                val fragment = FirstFragment.newInstance(dataToSend)
                setFragment(fragment)
            }


            fragment2Btn.setOnClickListener {
                // Activity -> Fragment로 데이터전달
                val bundle = Bundle()
                bundle.putString("data", "Activity -> Fragment\n로 데이터전달2")

                val fragment = SecondFragment()
                fragment.arguments = bundle

                setFragment(fragment)
            }
        }

        // MainActivity실행되자마자 나타날 프레그먼트
        setFragment(FirstFragment())
    }

    private fun setFragment(fragment : Fragment) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.frameLayout, fragment)
            .commit()
    }




}

MainActivity.kt

 

# Fragment에서 데이터 받기

arguments를 사용해서 데이터를 받아와서

text에 데이터를 뿌려준다

class SecondFragment : Fragment() {

    private lateinit var binding: FragmentSecondBinding

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

    }


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

        // MainActivity에서 보낸 데이터 받아오기
        val data = arguments?.getString("data")
        binding.Fragment2.text = data


        return binding.root
    }

}

SecondFragment.kt

 

 

# 실행화면

 

 

 

 

 

 

# Fragment -> Fragment 데이터 전달 

FirstFragment에 SecondFragment로 이동할 수 있는 버튼을 먼저 만들어준다

 

# Fragment에서 Fragment로 데이터 보내기

Activity->Fragment 부분과 크게 다른점이 없다

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    // Fragment -> Fragment 데이터전달
    binding.btnGofrag2.setOnClickListener {
        val dataToSend = "FirstFragment -> SecondFragment\n로 데이터전달"
        val fragment2 = SecondFragment.newInstance(dataToSend)

        requireActivity().supportFragmentManager.beginTransaction()
            .replace(R.id.frameLayout, fragment2)
            .commit()
    }

}

FirstFragment.kt

 

# Fragment에서 데이터받기

private const val ARG_PARAM1 = "param1"


class SecondFragment : Fragment() {

    private lateinit var binding: FragmentSecondBinding
    private var param1 : String? = null


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


        // FirstFragment에서 보낸 데이터를 꺼내서 param1에 넣어줌
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
        }
    }


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

		// 텍스트에 받아온 데이터 표시
        binding.Fragment2.text = param1

        return binding.root
    }


    companion object{

        // param1에 FirstFragment에서 전달한 데이터가 들어있음
        // 얘를 arguments에 저장
        fun newInstance(param1 : String) =
            SecondFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_PARAM1, param1)
                }
            }
    }


}

SecondFragment.kt

 

# 실행화면

 

 

 

 

 

# Fragment -> Activity 데이터 전달

 

# Fragment에서 Activity로 데이터 보내기

일단 SecondFragment에 버튼 하나를 만들어준다

Fragment에서 Actvity로 데이터를 전달하는 부분은 코드가 조금 다른데

먼저 인터페이스를 따로 생성해줘야한다

// interface를 통해서 데이터를 받아올것임
interface FragmentDataListener {
    fun onDataReceived(data : String)
}

FragmentDataListener.kt

 

 

이제 SecondFragment로 가서 listener변수에 방금 생성해줬던 인터페이스인 FragmentDataListner를 선언해준다

그런다음 onAttach()메소드에서 context를 listener에 할당해준다

이제 btnSendActivity버튼을 눌렀을때 listener.onDataReceived를 통해 데이터를 전달해준다

class SecondFragment : Fragment() {

    // listner에 인터페이스(FragmentDataListener) 선언
    private var listener : FragmentDataListener? = null


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

        // context에 FragmentDataListner가 구현되어있는지 체크(상속받았는지 체크)
        if (context is FragmentDataListener) {
            // context를 listener에 할당
            listener = context
        }else{
            Toast.makeText(context,"$context must implement FragmentDataListener", Toast.LENGTH_SHORT).show()
        }
    }



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

        binding.btnSendActivity.setOnClickListener {
            // listener를 통해 데이터전달
            val dataToSend = "Fragment -> Activity"
            listener?.onDataReceived(dataToSend)
        }


        return binding.root
    }

}

SecondFragment.kt

 

 

# Activity에서 데이터 받기

이제 MainActivity로 와서 FragmentDataListener 인터페이스를 상속받는다!!

아직 인터페이스를 오버라이딩을 안해줬기때문에,

onDataReceived함수를 오버라이딩해서 data를 받아와서, 여기서 Fragment에서 받은 데이터처리를 해준다!!

// FragmentDataListner 인터페이스 상속받음
class MainActivity : AppCompatActivity(), FragmentDataListener {

    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 뷰바인딩 사용
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

			...
        }
			...
    }

 			...
    }


    // secondFragment -> MainActivtiy
    // onDataReceived함수 오버라이딩해서 구현
    override fun onDataReceived(data1 : String){
        // Fragment에서 받은 데이터처리
        Toast.makeText(this, data1 , Toast.LENGTH_SHORT).show()
    }
}

MainActivity.kt

 

# 실행화면

 

 

 

 

 

 

 

 

 

 

 

 

# 참고자료 

https://cometome1004.tistory.com/156

 

안드로이드 스튜디오 - Activity 와 Fragment간 데이터 주고 받기

Activity -> Fragment 액티비티에서 프래그먼트로 데이터를 전송하기 위해선 Bundle이란 클래스를 사용한다. Bundle이란? -> 여러가지 타입의 값을 저장하는 Map 클래스 override fun onCreate(savedInstanceState: Bundl

cometome1004.tistory.com

https://juahnpop.tistory.com/225

 

안드로이드 코틀린 : Activity에서 Fragment에 데이터 보내기

Android Kotlin : Fragment 데이터 전달 및 상호 작용 지난 포스트에서는 Fragment 생성, 변경, 삭제와 같은 전환 방법에 대해 작성하였습니다. 이번 포스트는 Activity에서 Fragment 생성시 또는 생성되어 있는

juahnpop.tistory.com