btn1을 누르면 fragment가 생성되고 fragment안에있는 btn1을 누르면 숫자가 올라가는 앱을 만들거다.
우선 mainActivity에서 fragment를 만들고, 레이아웃을 만든다.
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
val manager = supportFragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.btn1.setOnClickListener {
val transaction1 = manager.beginTransaction()
val fragment1 = BlankFragment1()
transaction1.replace(R.id.frameArea, fragment1)
transaction1.addToBackStack(null)
transaction1.commit()
}
}
}
<?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"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn1"
android:text="btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/frameArea"
android:name="com.choidaehwan.fragmentlivedatalifecycleowner.BlankFragment1"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
데이터를 관리해줄 ViewModel을 만들어준다.
뷰모델에서는 라이브데이터를 사용하게끔 만들어준다.
class BlankViewModel1 : ViewModel() {
private var _mutableCount = MutableLiveData(0)
val liveCount : LiveData<Int>
get() = _mutableCount
fun plusCountValue(){
_mutableCount.value = _mutableCount.value!!.plus(1)
}
}
그리고 프래그먼트를 뷰결합과 뷰모델에 연동시킨다. 다만 여기서 observe
를 통해 데이터의 변화를 관찰할때 파라미터에 this 대신에 viewLifecycleOwner를 써준다.
fragment에서 this는 LifecycleOwner역할을 수행하는데 이는 fragment의 생명주기를 따라가기때문에 fragment view의 생명주기를 따르는 viewLifecycleOwner를 사용해야한다.
class BlankFragment1 : Fragment() {
private val TAG = "BlankFragment1"
private var _binding : FragmentBlank1Binding? = null
private val binding get() = _binding!!
private lateinit var viewModel: BlankViewModel1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentBlank1Binding.inflate(inflater, container, false)
val view = binding.root
viewModel = ViewModelProvider(this).get(BlankViewModel1::class.java)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btn1.setOnClickListener {
viewModel.plusCountValue()
}
// this 대신에 viewLifecycleOwner를 사용한다
viewModel.liveCount.observe(viewLifecycleOwner, Observer {
binding.text1.text = it.toString()
})
}
override fun onDestroyView() {
super.onDestroyView()
Log.d(TAG, "onDestroyView")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "onDestroy")
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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"
tools:context=".BlankFragment1">
<!-- TODO: Update blank fragment layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:textSize="60sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Frag1" />
<TextView
android:id="@+id/text1"
android:text="0"
android:textSize="60sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn1"
android:text="btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</FrameLayout>
이렇게하면 fragment에서 LiveData를 사용할 수 있다.