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를 사용할 수 있다.
