공식 문서
공식 예시 블로그
The ViewModel class is designed to hold and manage UI-related data in a life-cycle conscious way. This allows data to survive configuration changes such as screen rotations.
class MainActivity : AppCompatActivity() {
lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
val plusBtn : Button = findViewById(R.id.plus)
val minusBtn : Button = findViewById(R.id.minus)
val resultArea : TextView = findViewById(R.id.result)
resultArea.text= viewModel.getCount().toString()
plusBtn.setOnClickListener{
viewModel.plus()
resultArea.text= viewModel.getCount().toString()
}
minusBtn.setOnClickListener{
viewModel.minus()
resultArea.text= viewModel.getCount().toString()
}
}
}
ViewModelProvider로 MainViewModel을 불러와 viewModel 인스턴스를 만든다.
viewModel의 함수를 이용하여 값은 더하거나 빼준다.
class MainViewModel : ViewModel() {
var countValue = 0
init {
Log.d("MainViewModel", "init")
}
fun plus(){
countValue++
}
fun minus(){
countValue--
}
fun getCount() : Int {
return countValue
}
}
Activity뿐만 아니라 Fragment에서도 동일한 방식으로 ViewModel을 이용할 수 있다.
Activity의 값을 Fragment에서 쓰고 싶거나, Fragment에서 값을 ViewModel의 값으로 사용하기 위해 이 기능을 이용한다.
동일한 ViewModel을 사용하여 공유할 수 있다.
class MainActivity : AppCompatActivity() {
lateinit var binding : ActivityMainBinding
lateinit var viewModel : MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
binding.resultArea.text = viewModel.getCount().toString()
binding.plus.setOnClickListener {
viewModel.plus()
binding.resultArea.text = viewModel.getCount().toString()
}
binding.minus.setOnClickListener {
viewModel.minus()
binding.resultArea.text = viewModel.getCount().toString()
}
val manager = supportFragmentManager
binding.showFragment.setOnClickListener {
val transaction = manager.beginTransaction()
val fragment = TestFragment()
transaction.replace(R.id.frameArea, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
}
}
class TestFragment : Fragment() {
private lateinit var binding : FragmentTestBinding
private val viewModel : MainViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
// Inflate the layout for this fragment
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_test, container, false)
binding.fragmentTest.text = viewModel.getCount().toString()
return binding.root
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout
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">
<androidx.constraintlayout.widget.ConstraintLayout
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">
<TextView
android:id="@+id/resultArea"
android:text="0"
android:textSize="50sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/plus"
android:text="plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/minus"
android:text="minus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/showFragment"
android:text="showFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="@+id/frameArea"
android:background="#32a852"
android:layout_width="match_parent"
android:layout_height="200dp"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>