[Kotlin] Activity에서 Fragment로 데이터 전달
1. onAttach()에서 Context 파라미터를 이용하여 Activity 객체를 생성하는 방법
2. Bundle 객체를 생성해서 Fragment의 전달인자로 보내는 방법
3. ViewModel을 공유하는 방법
1. onAttach()에서 Context 파라미터로 Activity 객체 생성하여 전달받는 방법
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<Button
android:id="@+id/btnChange"
android:layout_width="match_parent"
android:layout_height="70dp"
android:textAllCaps="false"
android:text="Change Fragment"
android:textSize="22dp"/>
</LinearLayout>
fragment_red.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFBBBB">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:text="이름"/>
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_green.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BBFFBB">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:text="이름"/>
</androidx.constraintlayout.widget.ConstraintLayout>
FragmentGreen.kt
package com.jwsoft.kotlinproject
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
class FragmentGreen : Fragment() {
private lateinit var name: String
override fun onAttach(context: Context) {
super.onAttach(context)
name = (context as MainActivity).getName()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_green, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val tvName = view.findViewById<TextView>(R.id.tvName)
tvName.text = name
}
}
FragmentRed.kt
package com.jwsoft.kotlinproject
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
class FragmentRed : Fragment() {
private lateinit var name: String
override fun onAttach(context: Context) {
super.onAttach(context)
name = (activity as MainActivity).getName()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_red, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val tvName = view.findViewById<TextView>(R.id.tvName)
tvName.text = name
}
}
MainActivity.kt
package com.jwsoft.kotlinproject
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.FragmentTransaction
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val fragmentManager = supportFragmentManager
private lateinit var transaction: FragmentTransaction
private var isRed = false
private var name = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
transaction = fragmentManager.beginTransaction()
transaction.add(R.id.frameLayout, FragmentRed())
transaction.add(R.id.frameLayout, FragmentGreen())
transaction.commit()
btnChange.setOnClickListener {
transaction = fragmentManager.beginTransaction()
if (isRed) {
transaction.replace(R.id.frameLayout, FragmentGreen())
name = "James Kim Green"
} else {
transaction.replace(R.id.frameLayout, FragmentRed())
name = "James Kim Red"
}
isRed = !isRed
transaction.commit()
}
}
fun getName(): String {
return name
}
}
2. Bundle 객체를 생성해서 Fragment의 전달인자로 보내는 방법
fragment_red.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFBBBB">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:text="이름"/>
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_green.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BBFFBB">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:text="이름"/>
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<Button
android:id="@+id/btnChange"
android:layout_width="match_parent"
android:layout_height="70dp"
android:textAllCaps="false"
android:text="Change Fragment"
android:textSize="22dp"/>
</LinearLayout>
FragmentRed.kt
package com.jwsoft.kotlinproject
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
class FragmentRed : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_red, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val tvName = view.findViewById<TextView>(R.id.tvName)
val bundle = arguments
tvName.text = bundle?.getString("name")
}
}
FragmentGreen.kt
package com.jwsoft.kotlinproject
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
class FragmentGreen : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_green, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val tvName = view.findViewById<TextView>(R.id.tvName)
val bundle = arguments
tvName.text = bundle?.getString("name")
}
}
MainActivity.kt
package com.jwsoft.kotlinproject
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.FragmentTransaction
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val fragmentManager = supportFragmentManager
private lateinit var transaction: FragmentTransaction
private var isRed = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
transaction = fragmentManager.beginTransaction()
transaction.add(R.id.frameLayout, FragmentRed())
transaction.add(R.id.frameLayout, FragmentGreen())
transaction.commit()
btnChange.setOnClickListener {
transaction = fragmentManager.beginTransaction()
val bundle = Bundle()
if (isRed) {
bundle.putString("name", "James Kim Green")
transaction.replace(R.id.frameLayout, FragmentGreen().apply { arguments = bundle })
} else {
bundle.putString("name", "James Kim Red")
transaction.replace(R.id.frameLayout, FragmentRed().apply { arguments = bundle })
}
isRed = !isRed
transaction.commit()
}
}
}
3. ViewModel을 공유하는 방법
fragment_red.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFBBBB">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:text="이름"/>
</androidx.constraintlayout.widget.ConstraintLayout>
fragment_green.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BBFFBB">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
tools:text="이름"/>
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<Button
android:id="@+id/btnChange"
android:layout_width="match_parent"
android:layout_height="70dp"
android:textAllCaps="false"
android:text="Change Fragment"
android:textSize="22dp"/>
</LinearLayout>
ActivityViewModel.kt
package com.jwsoft.kotlinproject
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class ActivityViewModel : ViewModel() {
var name: MutableLiveData<String> = MutableLiveData()
}
FragmentRed.kt
package com.jwsoft.kotlinproject
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
class FragmentRed : Fragment() {
private lateinit var viewModel: ActivityViewModel
private lateinit var tvName: TextView
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewModel = ViewModelProvider(requireActivity(), ViewModelProvider.NewInstanceFactory())
.get(ActivityViewModel::class.java)
return inflater.inflate(R.layout.fragment_red, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
tvName = view.findViewById(R.id.tvName)
viewModel.name.observe(this, Observer {
tvName.text = it
})
}
}
FragmentGreen.kt
package com.jwsoft.kotlinproject
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
class FragmentGreen : Fragment() {
private lateinit var viewModel: ActivityViewModel
private lateinit var tvName: TextView
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewModel = ViewModelProvider(requireActivity(), ViewModelProvider.NewInstanceFactory())
.get(ActivityViewModel::class.java)
return inflater.inflate(R.layout.fragment_green, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
tvName = view.findViewById(R.id.tvName)
viewModel.name.observe(this, Observer {
tvName.text = it
})
}
}
MainActivity.kt
package com.jwsoft.kotlinproject
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.ViewModelProvider
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: ActivityViewModel
private val fragmentManager = supportFragmentManager
private lateinit var transaction: FragmentTransaction
private var isRed = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())
.get(ActivityViewModel::class.java)
transaction = fragmentManager.beginTransaction()
transaction.add(R.id.frameLayout, FragmentRed())
transaction.add(R.id.frameLayout, FragmentGreen())
transaction.commit()
btnChange.setOnClickListener {
transaction = fragmentManager.beginTransaction()
if (isRed) {
viewModel.name.value = "James Kim Green"
transaction.replace(R.id.frameLayout, FragmentGreen())
} else {
viewModel.name.value = "James Kim Red"
transaction.replace(R.id.frameLayout, FragmentRed())
}
isRed = !isRed
transaction.commit()
}
}
}