์์ฆ MVVM
์ ๋ํด์ ๊ณต๋ถํ๊ณ ์๋ค. ์ง๊ธ๊น์ง ์ฑ ๊ตฌํํ ๋ ๊ทธ๋ฅ ์กํฐ๋นํฐ์ ๋ค ๋๋ ค๋ฐ์์๋๋ฐ ๋ชจ๋ธ์ด๋ ๋ทฐ๊ฐ ๋๋ฌด ๊ฐํ๊ฒ ๊ฒฐํฉ๋์ด ์๋ ๋๋์ด ๊ฐํ๋ค. ๋ํ ๋๋ถ๋ถ์ ๋ก์ง์ ๋ทฐ(์กํฐ๋นํฐ)์์ ์ฒ๋ฆฌํ๊ณ ํ๊ณ ์์๊ณ ์ฌ์ฌ์ฉ์ฑ์ด ๋งค์ฐ ๋จ์ด์ก์๋ค. ์ค์ ๋ก ๊ฒจ์ธ๋ฐฉํ์ ์งํํ๋ ๊ธ๋ก๋ฒ์ธ์ฌํธ๋ ๋ ์ดํ ์ ํ๋ ๋ง๋ค์๊ณ ๋๋ฆ ๋ถ๋ฆฌํ๋ค๊ณ ๋ถ๋ฆฌํ๋๋ฐ ์ง์ง ์ฌ์ฌ์ฉ์ฑ์ด 0 ์ด์๋ค. MVC
๊ฐ ๊ตฌํํ๊ธฐ๋ ์ ๋ง ํธํ์ง๋ง ์ด ๊ธฐํ์ ํจํด ๊ณต๋ถ๋ ํ ๊ฒธ MVVM
์ ์ ํ๊ฒ ๋์๋ค. ๋ฌผ๋ก MVC
๋ณด๋ค MVVM
์ด ๊ตฌํํ๊ธฐ ์ด๋ ต๋ค. ๊ทธ๋ ์ง๋ง ๋ถํ ์ค ๋คํ! ๊ตฌ๊ธ์์ MVVM
์ ์ฝ๊ฒ ๊ตฌํํ ์ ์๋๋ก AAC(Android Architecture Component)
๋ฅผ ์ง์ํ๊ณ ์๋ค.
๊ทธ๋์ MVVM์ด ๋ญ์์?
MVVM์ Model, View, View Model ๋ก ๋ถ๋ฆฌ๋ ์ํคํ
์ณ ๋์์ธ ํจํด
์ด๋ค. MVC
์์ ๋ชจ๋ธ๊ณผ ๋ทฐ์ ๊ฐํ ์์กด์ฑ, MVP
์์ ๋ทฐ์ ํ๋ ์ ํฐ์ ๊ฐํ ์์กด์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๋์์ธ ํจํด์ผ๋ก Model ์ ์ดํ๋ฆฌ์ผ์ด์
์์ ์ฌ์ฉ๋๋ ๋ฐ์ดํฐ์ ๊ทธ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ถ๋ถ์ด๋ค. View ๋ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๋ UI ๋ถ๋ถ์ด๊ณ View Model ์ View ๋ฅผ ์ํ View Model ๋ก, View ๋ฅผ ํํํ๊ธฐ ์ํ Model ์ ์ฒ๋ฆฌํ๋ ๋ถ๋ถ์ด๋ค.
๊ตฌ๊ธ์์๋ ์๋์ ๊ฐ์ ์ํคํ ์ณ๋ฅผ ๊ถ๊ณ ํ๊ณ ์๋ค.
์ฃผ์๊น๊ฒ ๋ด์ผํ๋ ๊ฒ์ ํ์ดํ์ ๋ฐฉํฅ
์ด๋ค. ๋ชจ๋ ํ์ดํ๊ฐ ๋จ๋ฐฉํฅ์ผ๋ก ์ฐ๊ฒฐ๋์ด ์๋ค. ์กํฐ๋นํฐ์ ํ๋๊ทธ๋จผํธ๋ ๋ทฐ๋ชจ๋ธ์ ์กด์ฌ๋ฅผ ์์ง๋ง ๋ฐ๋๋ก ๋ทฐ๋ชจ๋ธ์ ์กํฐ๋นํฐ์ ํ๋๊ทธ๋จผํธ์ ์กด์ฌ์ ๋ํด ์์ง ๋ชปํ๋ค. ๋ทฐ๋ชจ๋ธ์ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ๊ณ ๋ ํฌ์งํ ๋ฆฌ๋ ๋ชจ๋ธ์ ์ฐธ์กฐํ๋ค. ๋ ํฌ์งํ ๋ฆฌ ์ญ์ ๋ทฐ๋ชจ๋ธ์ ์กด์ฌ๋ฅผ ์์ง ๋ชปํ๋ค. ๊ตฌ๊ธ ๊ณต์ ์์ - Build an App with Architecture Components (GDD India '17) ์์๋ ๊ฐ ํด๋์ค์ ํ์ ํด๋์ค๋ง ์ฐธ์กฐํ ์ ์๋ค๊ณ ์ธ๊ธํ๊ณ ์๋ค. ์ฆ, ์กํฐ๋นํฐ๊ฐ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ์ฐธ์กฐํด์๋ ์๋๋ค๋ ์๋ฏธ๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด์ ์ํคํ ์ณ ๊ตฌ์กฐ๊ฐ ์ด๋ป๊ฒ ๋ณํ๋์ง๋ฅผ ๋ณด๊ธฐ ์ํด ์๋์ ๊ฐ์ ์์๋ก ์ฝ๋๋ฅผ ์์ ํ๋ฉด์ ์งํํ๋๋ก ํ๊ฒ ๋ค.
ViewBinding
-> DataBinding
-> DataBinding + ViewModel
-> DataBinding + ViewModel + LiveData
1. ViewBinding
์ ๋ง ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค. ์กํฐ๋นํฐ
์ ๋ชจ๋ ๋ด์ฉ์ ๋๋ ค๋ฐ๋๋ค. findViewById
๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ViewBinding
์ ์ฌ์ฉํ๋๋ฐ ViewBinding, ์ด ์น๊ตฌ ์ ๋ง ์ง๊ตญ์ด๋ค. ํ ๋ฒ ์ฌ์ฉํ๋ฉด findViewById ๋ ๊ฑฐ๋ค๋ ๋ ์๋ณด๊ฒ ๋๋ฌ๊น?
Activity_Main.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"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/displayNumberTextView"
android:layout_width="0dp"
android:layout_height="100dp"
android:layout_marginHorizontal="18dp"
android:gravity="center"
android:textSize="50sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="20" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/plusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="18dp"
android:src="@drawable/ic_baseline_add_24"
app:layout_constraintBottom_toBottomOf="@+id/minusButton"
app:layout_constraintEnd_toStartOf="@+id/minusButton" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/minusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="18dp"
android:layout_marginBottom="18dp"
android:src="@drawable/ic_baseline_remove_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
increase
์ decrease
๋ฅผ ๊ตฌํํ๊ณ setOnClickListener
์ ์ฐ๊ฒฐํ๋ค.
package com.example.basic_mvvm
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.basic_mvvm.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private val binding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
private var num : Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setContentView(binding.root)
bindViews()
increase()
decrease()
}
private fun bindViews() {
binding.displayNumberTextView.text = num.toString()
}
private fun increase() {
binding.plusButton.setOnClickListener {
num += 1
binding.displayNumberTextView.text = num.toString()
}
}
private fun decrease() {
binding.minusButton.setOnClickListener {
num -= 1
binding.displayNumberTextView.text = num.toString()
}
}
}
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์ง๊ณ ๋น๋๋ฅผ ์งํํด๋ณด์.
์ ์์ ์ผ๋ก ์ฑ์ด ์๋ํ์ง๋ง ์กํฐ๋นํฐ๋ฅผ ์ฌ์คํ(ํ๋ฉด ์ ํ)์ด ๋ฐ์ํ๋ฉด ๊ฐ์ด ์ด๊ธฐํ๋๋ค. ํ๋ฉด ์ ํ์ด ๋ฐ์ํ ๋ ๊ธฐ์กด ์กํฐ๋นํฐ๊ฐ onDestory ๋๊ณ ๋ค์ onCreate ๋์ด์ ๋ฐ์ํ๋ ๋ฌธ์ ์ด๋ค. ๋ฌผ๋ก , savedInstance ๋ฅผ ํ์ฉํ๋ฉด ์ด๋ฅผ ํด๊ฒฐํ ์ ์์ง๋ง viewModel ์ ์ฌ์ฉํ ๊ฒ์ด๋ฏ๋ก ์ฐ์ ๋์ด๊ฐ๋๋ก ํ์. ์กํฐ๋นํฐ๋ฅผ ์ฌ์คํํ๋ฉด ๊ฐ์ด ์ด๊ธฐํ๋๋ค๋ ๊ฒ์ ์ด์ ์ ๋ง์ถ์.
2. ViewBinding -> DataBinding
์์ ViewBinding
์ผ๋ก ๊ตฌํํ ๋ถ๋ถ์ DataBinding
์ผ๋ก ๋ณ๊ฒฝํด์คฌ๋ค. DataBindingUtil
์ ์ฌ์ฉํ๋ค. DataBinding ์ ํ๋ก๊ทธ๋๋งคํฑ ๋ฐฉ๋ฒ์ด ์๋ ์ ์ธ์ ํ์์ผ๋ก ๋ ์ด์์์ UI ๊ตฌ์ฑ์์
๋ฅผ ์ฑ์ ๋ฐ์ดํฐ ์์ค์ ๊ฒฐํฉํ ์ ์๊ฒ ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ด๋ค. DataBinding ์ ์ฅ์ ์ ๊ธฐ์กด์ ๋ทฐ์ ์ ์ํ๋ setValue
๋ onClick
๋ค์ ๋ ์ด์์์ ๊ตฌํํจ์ผ๋ก์จ ๋ทฐ๊ฐ ์กฐ๊ธ ๋ ๊น๋ํด์ง๋ค.
// ๊ธฐ์กด ์ฝ๋
binding.displayNumbertextView.text = num.toString()
// Databinding ์ ์ฌ์ฉํ ์ฝ๋
<TextView
android:text="@{mainactivity.num}"/>
DataBinding ์ ์ฌ์ฉํ๊ธฐ ์ํด์ XML
ํ์ผ์ ๋ณ๊ฒฝํด์ค์ผ ํ๋ค. ๊ธฐ์กด ๋ ์ด์์
์ <layout>
์ผ๋ก ๊ฐ์ธ์ค๋ค. ์ดํ <data>
์์ฑ์์ ์ด๋ค ๋ณ์๋ฅผ ๋ณด์ฌ์ค์ง๋ฅผ ์ ์ํ๋ค.
<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">
<data>
<variable
name="mainactivity"
type="com.example.basic_mvvm.MainActivity" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:text="@{mainactivity.num}"/>
// ์ดํ ์๋ต
DataBinding ์ ์ฌ์ฉํ๋ฉด ViewBinding ์ ์ฌ์ฉํ ๋๋ณด๋ค ์ข ๋ ๊ด์ฌ์ฌ๋ฅผ ์ข ๋ ๋ถ๋ฆฌ์ํฌ ์ ์๋ค. ๊ธฐ์กด์๋ ๋ชจ๋ ๋น์ง๋์ค ๋ก์ง์ ์กํฐ๋นํฐ์ ๋๋ ค ๋ฐ๊ณ ๋ทฐ์ ๋ํ ๊ฐ๋จํ ์ฒ๋ฆฌ๋ค(setValue, onClick)์ ๋ทฐ์์ ์ฒ๋ฆฌํ์ง๋ง XML
์์ ์ฒ๋ฆฌํ๋๋ก ๋ณ๊ฒฝํด์คฌ๋ค.
์ด์ ๋น๋๋ฅผ ํด๋ณด์!
ํ์ง๋ง ์ฌ์ ํ ๊ฐ์ด ์ ์ฅ๋๊ณ ์์ง ์๋ค. ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๋ณด์.
3. DataBinding -> DataBinding + ViewModel
AAC
์ ๋ทฐ๋ชจ๋ธ
์ด ๋น์ ๋ฐํ ์ฐจ๋ก์ด๋ค. ์ฐ์ ๋ทฐ๋ชจ๋ธ์ ์กํฐ๋นํฐ๋ณด๋ค ๊ธด ์๋ช
์ฃผ๊ธฐ๋ฅผ ๊ฐ์ง๋ค.
MainActivity.kt
๋ทฐ๋ชจ๋ธ
์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ViewModelProviders
์ ์ฌ์ฉํด์ผ ํ๋ค. ViewModel
์ ์ค์ฐ๋, LifecycleOwner
๋ฅผ ๋ฃ์ด์ค๋ค. LifecycleOnwer์ ์๋ช
์ฃผ๊ธฐ๋ฅผ ๋ฐ๋ฅด๊ฒ ๋ค๋ ์๋ฏธ์ด๋ค. (Deprecated ๋์๋ค... ViewModelProvider ๋ฅผ ์ฌ์ฉํ๋๋ก ํ์)
package com.example.basic_mvvm
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProviders
import com.example.basic_mvvm.databinding.ActivityMainBinding
import com.example.basic_mvvm.viewmodel.MainViewModel
class MainActivity : AppCompatActivity() {
private val binding by lazy {
DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
}
private val viewModel by lazy {
ViewModelProviders.of(this).get(MainViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bindViews()
increase()
decrease()
}
private fun bindViews() {
binding.displayNumberTextView.text = viewModel.getNumber().toString()
}
private fun increase() {
binding.plusButton.setOnClickListener {
viewModel.increase()
binding.displayNumberTextView.text = viewModel.getNumber().toString()
}
}
private fun decrease() {
binding.minusButton.setOnClickListener {
viewModel.decrease()
binding.displayNumberTextView.text = viewModel.getNumber().toString()
}
}
}
ViewModel.kt
์ฝ๋๊ฐ ์ ๋ง ๋ถ์คํ์ง๋ง num
์ฆ๊ฐ์ ๊ดํ ๋น์ฆ๋์ค ๋ก์ง์ ์กํฐ๋นํฐ
์์ ๋ถ๋ฆฌํ๋ค.
package com.example.basic_mvvm.viewmodel
import androidx.lifecycle.ViewModel
class MainViewModel : ViewModel() {
var num: Int = 0
fun getNumber(): Int = num
fun increase() = num++;
fun decrease() = num--;
}
ํ๋ฉด์ด ๋ณ๊ฒฝ๋์ด๋ ๊ฐ์ด ์ด๊ธฐํ๋์ง ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค!
'๐ป ๊ฐ๋ฐ > Android' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android] ์๋ฆผ ํด๋ฆญ์ Activity, Fragment๋ก ์ด๋ (0) | 2022.06.08 |
---|---|
[Android] ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์์ผ ํต์ ์ผ๋ก ์ด๋ฒคํธ ์์ ํ ์๋ฆผ (0) | 2022.06.08 |
[Android] MVVM ํจํด ์ ์ฉ๊ธฐ - 2 (0) | 2022.05.14 |
[Android] ์นด๋ฉ๋ผ ๋๋ ๊ฐค๋ฌ๋ฆฌ์์ ์ด๋ฏธ์ง ๊ฐ์ ธ์ค๊ธฐ (0) | 2022.02.06 |
[Android] ๋ค๊ตญ์ด ์ง์ (0) | 2022.01.13 |