Activity에서 Fragment로 데이터를 전달할 때는 프래그먼트의 인스턴스를 생성하고 newInstance 메소드를 통해 데이터를 전달한다. Bundle 객체를 사용하여 데이터를 프래그먼트의 인자(arguments)로 설정하고, 인자를 프래그먼트가 받아 사용한다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.run {
fragment1Btn.setOnClickListener {
// Activity -> FirstFragment
val dataToSend = "Hello First Fragment: \n From Activity"
val fragment = FirstFragment.newInstance(dataToSend) // Instance를 생성해서 String 데이터를 전달
setFragment(fragment)
}
fragment2Btn.setOnClickListener {
// 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("")
}
}
}
private const val ARG_PARAM1 = "param1"
class FirstFragment : Fragment() {
private val binding by lazy { FragmentFirstBinding.inflate(layoutInflater) }
private var param1: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1) // Bundle 안에 있는 값을 꺼내서 param1에 넣음
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Activity -> FirstFragment
binding.tvFrag1Text.text = param1
}
companion object {
@JvmStatic
fun newInstance(param1: String) = // Instance가 생성
// Activity -> FirstFragment
FirstFragment().apply {
arguments = Bundle().apply { // Fragment의 arguments에 Bundle() 객체로 넣음
putString(ARG_PARAM1, param1)
}
}
}
}
private const val ARG_PARAM1 = "param1"
class SecondFragment : Fragment() {
private var _binding: FragmentSecondBinding? = null
private val binding get() = _binding!!
private var param1: String? = null
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)
binding.tvFrag2Text.text = param1
}
companion object {
@JvmStatic
fun newInstance(param1: String) =
SecondFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
}
}
}
}
한 프래그먼트에서 다른 프래그먼트로 데이터를 전달 할 때는, 첫 번째 프래그먼트에서 두 번째 프래그먼트의 newInstance 메소드를 사용하여 인스턴스를 생성하고, 데이터를 전달 한다.
private const val ARG_PARAM1 = "param1"
class FirstFragment : Fragment() {
private val binding by lazy { FragmentFirstBinding.inflate(layoutInflater) }
private var param1: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1) // Bundle 안에 있는 값을 꺼내서 param1에 넣음
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Activity -> FirstFragment
binding.tvFrag1Text.text = param1
// Fragment -> Fragment
binding.btnGoFrag2.setOnClickListener {
val dataToSend = "Hello Fragment! \n From Fragment1"
val fragment2 = SecondFragment.newInstance(dataToSend)
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.frameLayout, fragment2)
.addToBackStack(null)
.commit()
}
}
companion object {
@JvmStatic
fun newInstance(param1: String) = // Instance가 생성
// Activity -> FirstFragment
FirstFragment().apply {
arguments = Bundle().apply { // Fragment의 arguments에 Bundle() 객체로 넣음
putString(ARG_PARAM1, param1)
}
}
}
}
프래그먼트에서 액티비티로 데이터를 전달 할 때는 콜백 인터페이스를 정의하고, 해당 인터페이스를 액티비티가 구현하도록 한다. 프래그먼트는 이 인터페이스를 사용하여 액티비티에 데이터를 전달한다.
interface FragmentDataListener {
fun onDataReceived(data: String)
}
class MainActivity : AppCompatActivity(), FragmentDataListener {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.run {
fragment1Btn.setOnClickListener {
// Activity -> FirstFragment
val dataToSend = "Hello First Fragment: \n From Activity"
val fragment =
FirstFragment.newInstance(dataToSend) // Instance를 생성해서 String 데이터를 전달
setFragment(fragment)
}
fragment2Btn.setOnClickListener {
// 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("")
}
}
override fun onDataReceived(data: String) {
Toast.makeText(this, data, Toast.LENGTH_SHORT).show()
}
}
private const val ARG_PARAM1 = "param1"
class SecondFragment : Fragment() {
// SecondFragment -> Activity
private var listener: FragmentDataListener? = null
private var _binding: FragmentSecondBinding? = null
private val binding get() = _binding!!
private var param1: String? = null
override fun onAttach(context: Context) {
super.onAttach(context)
// 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)
// Fragment -> Fragment
binding.tvFrag2Text.text = param1
// SecondFragment -> Activity
binding.btnsendActivity.setOnClickListener {
val dataToSend = "Hello From SecondFragment!"
listener?.onDataReceived(dataToSend)
}
}
companion object {
@JvmStatic
fun newInstance(param1: String) =
SecondFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
}
}
}
}