MVC
MVC는 가장 기본적인 패턴이라고 할 수 있다.
사용자의 액션을 Controller로 받고 Model을 업데이트 한다. Controller는 Model을 나타낼 View를 선택하고 View는 이를 이용해 화면에 나타낸다.
그럼 이를 코드로 알아보자!😆
비밀번호 4개를 입력했을 때 언락(unlock)이 됐다는 텍스트를 표시하는 예시이다.
여기서 MainActivity가 Controller의 역할을 한다.
// Controller
class MainActivity : AppCompatActivity() {
lateinit var binding : ActivityMainBinding
var model = Model()
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.mainActivity = this
}
fun clickNumber(i :Int){
Toast.makeText(this, "$i 번을 클릭했습니다.", Toast.LENGTH_SHORT).show()
model.inputPassword(i)
if(model.password.size == 4 && model.checkPassword()){
// 4자리 이상 비밀번호가 1234
binding.messageSuccess.visibility = View.VISIBLE
}
}
}
class Model {
var password : MutableList<Int> = mutableListOf()
fun inputPassword(i : Int){
if(password.size < 4){
password.add(i)
}
}
fun checkPassword() : Boolean{
var trueCount = 0
var savePassword = mutableListOf(1,2,3,4)
for (i in 0 until savePassword.size){
if(savePassword.get(i)==password.get(i)){
trueCount++
}
}
return trueCount == 4
}
}
MVP
Presenter가 View와 Model을 제어한다.
Model이 View를 직접적으로 제어할 수 없는 것이 MVC와의 차이점이다.
Controller는 단순히 정보만 입력받는 interface로 변환된다.
다른 Activity가 생겼을 때 Presenter를 손쉽게 이식할 수 있다는 장점을 가지고 있다.
그럼 MVP도 코드로 알아보자!😍
MVC와는 다르게 interface파일이 추가되었다.
class MainActivity : AppCompatActivity(), ViewInterface{
lateinit var binding : ActivityMainBinding
var presenter = Presenter(this)
var model = Model()
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.mainActivity = this
}
fun clickNumber(i :Int){
presenter.clickNumber(i)
}
override fun toastMessage(i: Int) {
Toast.makeText(this, "$i 번을 클릭했습니다.", Toast.LENGTH_SHORT).show()
}
override fun checkPasswordMessage() {
binding.messageSuccess.visibility = View.VISIBLE
}
}
class Presenter(var viewInterface : ViewInterface) {
var model = Model()
fun clickNumber(i :Int){
viewInterface.toastMessage(i)
model.inputPassword(i)
if(model.password.size == 4 && model.checkPassword()){
viewInterface.checkPasswordMessage()
}
}
}
interface ViewInterface {
fun toastMessage(i : Int)
fun checkPasswordMessage()
}
MVVM
앞서 설명했던 MVC와 MVP를 보완하기 위해 MVVM이 나왔다.
여러 개의 뷰를 연결할 수 있는 것이 MVP와의 차이점이다.
여러 개를 연결하게 되면 Presenter가 아니라 View Model이라고 부르는 것이다.
MVVM도 코드로 이해해보자!🙂
class MainActivity : AppCompatActivity(){
lateinit var binding : ActivityMainBinding
var viewModel = ViewModel()
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.viewModel = viewModel
viewModel.toastMessage.observe(this, Observer{i ->
Toast.makeText(this, "$i 번을 클릭했습니다.", Toast.LENGTH_SHORT).show()
})
viewModel.checkPasswordMessage.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback(){
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
if(viewModel.checkPasswordMessage.get() == true){
binding.messageSuccess.visibility = View.VISIBLE
}else{
binding.messageSuccess.visibility = View.GONE
}
}
})
}
}
class Model {
var password : MutableList<Int> = mutableListOf()
fun inputPassword(i : Int){
if(password.size < 4){
password.add(i)
}
}
fun checkPassword() : Boolean{
var trueCount = 0
var savePassword = mutableListOf(1,2,3,4)
for (i in 0 until savePassword.size){
if(savePassword.get(i)==password.get(i)){
trueCount++
}
}
return trueCount == 4
}
}
class ViewModel {
var toastMessage = MutableLiveData<Int>()
var checkPasswordMessage = ObservableField<Boolean>(false)
var model = Model()
fun clickNumber(i :Int){
toastMessage.value = i
model.inputPassword(i)
if(model.password.size == 4 && model.checkPassword()){
// 비밀번호가 맞을 경우 True
checkPasswordMessage.set(true)
}
}
}
즉, 아래와 같이 변수로 선언해서 사용하면 다중 뷰를 무한히 연결시켜서 사용할 수 있는 것이다.
var checkPasswordMessage = ObservableField<Boolean>(false)