728x90
- 액티비티 → 프래그먼트 데이터 전달
- 프래그먼트 → 프래그먼트 데이터 전달
- 프래그먼트 → 액티비티 데이터 전달
1. 액티비티에서 프래그먼트로 데이터를 전달하는 경우
MainActivity.kt (데이터를 보내는 액티비티)
더보기
package com.android.ex_view2
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import com.android.ex_view2.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.run {
btnFragment1.setOnClickListener {
// [1] Activity -> FirstFragment
val dataToSend = "Hello First Fragment! \n From Activity"
// FirstFragment의 인스턴스 생성, newInstance 메서드에 데이터를 전달하여 프래그먼트를 설정(set)
val fragment = FirstFragment.newInstance(dataToSend)
setFragment(fragment)
}
btnFragment2.setOnClickListener {
// [1] Activity -> SecondFragment
val dataToSend = "Hello Second Fragment! \n From Activity"
// 21라인과 동일
val fragment = SecondFragment.newInstance(dataToSend)
setFragment(fragment)
}
}
setFragment(FirstFragment())
}
private fun setFragment(frag: Fragment) {
supportFragmentManager.commit {
replace(R.id.framLayout, frag)
setReorderingAllowed(true)
addToBackStack("")
}
}
}
- 프래그먼트의 인스턴스를 생성하고, newInstance 메서드를 통해 데이터를 전달한다
- Bundle 객체를 사용하여 데이터를 프래그먼트의 인자(arguments)로 설정하고
- 이 인자를 프래그먼트가 받아서 사용한다
FirstFragment.kt (데이터를 받는 프래그먼트)
더보기
package com.android.ex_view2
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.android.ex_view2.databinding.FragmentFirstBinding
private const val ARG_PARAM1 = "param1"
class FirstFragment : Fragment() {
private var param1: String? = null
private val binding by lazy { FragmentFirstBinding.inflate(layoutInflater) }
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? {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// [1] Activity -> FirstFragment
binding.tvFrag1Text.text = param1
}
companion object {
@JvmStatic
fun newInstance(param1: String) =
FirstFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
}
}
}
}
- newInstance 메서드에서 전달받은 데이터를 Bundle에 담고, 프래그먼트의 인자로 설정한다
- onViewCreated에서 인자로 받은 데이터를 텍스트 뷰에 설정한다
결과
2. 프래그먼트에서 프래그먼트로 데이터를 전달하는 경우
1번과 방법은 동일
FirstFragment.kt (데이터를 보내는 프래그먼트)
더보기
package com.android.ex_view2
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.android.ex_view2.databinding.FragmentFirstBinding
private const val ARG_PARAM1 = "param1"
class FirstFragment : Fragment() {
private var param1: String? = null
private val binding by lazy { FragmentFirstBinding.inflate(layoutInflater) }
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? {
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// [1] Activity -> FirstFragment
binding.tvFrag1Text.text = param1
// [2] Fragment -> Fragment
binding.btnGoFrag2.setOnClickListener {
val dataToSend = "Hello Fragment2! \n From Fragment1"
val fragment2 = SecondFragment.newInstance(dataToSend)
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.framLayout, fragment2)
.addToBackStack(null)
.commit()
}
}
companion object {
@JvmStatic
fun newInstance(param1: String) =
FirstFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
}
}
}
}
- (1번에서 35 ~ 43만 추가됨 && 나머지 과정 동일) fragment_first.xml에 버튼을 추가해 준다(btn_goFrag2)
- 버튼 클릭 시 SecondFragment의 새 인스턴스를 생성하고, newInstance 메서드를 사용하여 데이터를 전달한다
- 데이터를 전달한 후, 프래그먼트 트랜잭션을 통해 두 번째 프래그먼트를 시작한다
SecondFragment.kt(데이터를 받는 프래그먼트)
더보기
package com.android.ex_view2
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.android.ex_view2.databinding.FragmentFirstBinding
import com.android.ex_view2.databinding.FragmentSecondBinding
private const val ARG_PARAM1 = "param1"
class SecondFragment : Fragment() {
private var param1: String? = null
private val binding by lazy { FragmentSecondBinding.inflate(layoutInflater) }
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? {
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) =
SecondFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
}
}
}
}
- (받는 코드는 1번과 완전 동일함)
- newInstance 메서드로 전달받은 데이터를 Bundle에 담는다
- onCreate 또는 onViewCreated에서 Bundle로부터 데이터를 추출하여 사용한다
결과
3. 프래그먼트에서 액티비티로 데이터를 전달하는 경우
- 콜백 인터페이스를 정의하고, 해당 인터페이스를 액티비티가 구현하도록 해야 한다
- 프래그먼트는 이 인터페이스를 사용하여 액티비티에 데이터를 전달한다
FragmentDataListener 인터페이스 생성
File → New → Kotlin Class/File → Interface를 이용하여 인터페이스 생성
package com.android.ex_view2
interface FragmentDataListener {
fun onDataReceived(data: String)
}
SecondFragment.kt (데이터를 보내는 프래그먼트)
더보기
package com.android.ex_view2
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.android.ex_view2.databinding.FragmentFirstBinding
import com.android.ex_view2.databinding.FragmentSecondBinding
import java.lang.RuntimeException
private const val ARG_PARAM1 = "param1"
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!!
// private val binding by lazy { FragmentSecondBinding.inflate(layoutInflater) }
override fun onAttach(context: Context) {
super.onAttach(context)
// [3] SecondFragment -> Activity
// context is FragmentDataListener = MainActivity.kt 에 FragmentDataListener가 (구현 되어) 있는지 체크
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.btnSendToActivity.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)
}
}
}
}
- FragmentDataListener 인터페이스를 정의하고, 프래그먼트가 액티비티에 붙을 때(onAttach),
액티비티가 이 인터페이스를 구현했는지 확인한다 - 버튼 클릭 리스너에서 onDataReceived 메서드를 호출하여 데이터를 액티비티에 전달한다
MainActivity.kt (데이터를 받는 액티비티)
더보기
package com.android.ex_view2
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import com.android.ex_view2.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity(), FragmentDataListener {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.run {
btnFragment1.setOnClickListener {
// [1] Activity -> FirstFragment
val dataToSend = "Hello First Fragment! \n From Activity"
// FirstFragment의 인스턴스 생성, newInstance 메서드에 데이터를 전달하여 프래그먼트를 설정(set)
val fragment = FirstFragment.newInstance(dataToSend)
setFragment(fragment)
}
btnFragment2.setOnClickListener {
// [1] Activity -> SecondFragment
val dataToSend = "Hello Second Fragment! \n From Activity"
// 21라인과 동일
val fragment = SecondFragment.newInstance(dataToSend)
setFragment(fragment)
}
}
setFragment(FirstFragment())
}
private fun setFragment(frag: Fragment) {
supportFragmentManager.commit {
replace(R.id.framLayout, frag)
setReorderingAllowed(true)
addToBackStack("")
}
}
// [3] SecondFragment -> Activity
override fun onDataReceived(data: String) {
// Fragment에서 받은 데이터를 처리
Toast.makeText(this, data, Toast.LENGTH_SHORT).show()
}
}
- MainActivity는 FragmentDataListener 인터페이스를 구현하고, onDataReceived 메서드를 오버라이드해서
프래그먼트로부터 데이터를 받는다 - 데이터를 받으면 Toast메시지로 표시하도록 한다
결과
728x90
'코틀린(Kotlin) > TIL' 카테고리의 다른 글
[코틀린(Kotlin)] 알림 (2) | 2024.01.07 |
---|---|
[코틀린(Kotlin)] 다이얼로그 (0) | 2024.01.07 |
[코틀린(Kotlin)] 프래그먼트 (Fragment) (0) | 2024.01.07 |
[코틀린(Kotlin)] 리사이클러 뷰 (RecyclerView) (1) | 2024.01.05 |
[코틀린(Kotlin)] 어댑터 뷰(AdapterView), 리스트 뷰(ListView), 그리드 뷰(GridView) (1) | 2024.01.05 |