Android는 사실 Class 하나로 MVP의 처리가 가능한 구조로 만들 수 있지만, 코드가 1000줄과 같이 넘어간다면 가독성이 떨어지고 유지보수 하는데 힘이 든다.
이에 Business Logic을 Model, View, Presenter로 분리함으로써 명확한 업무 분담을 행하도록 하자!
이는 MVC와 다르게 UI(View)와 로직(Model)을 완전히 분리하고, 서로 간에 상호작용을 Presenter에 그 역할을 줌으로써, 서로의 영향(의존성)을 최소화한다.
(모델은 뷰를 직접적으로 전혀 컨트롤하지 못하게 된다.)
더하여서 새로운 액티비티를 생성했을 때, 손쉽게 프리젠터를 그쪽으로 이식할 수 있다.
(Model-View-Presenter)

Model
데이터와 비즈니스 로직을 담당한다. 데이터를 처리하고 저장하며, 프리젠터와 통신하여 데이터의 변경 사항을 전달하는 역할.
View
사용자 인터페이스(UI)를 표시하며, 사용자의 입력을 받아 처리한다. 프리젠터와 상호작용하여 필요한 데이터를 요청하고, 데이터의 변경 사항을 표시.
Presenter
뷰와 모델 사이의 중재자 역할. 뷰로부터 사용자 입력을 받아 모델에 전달하고, 모델에서 받은 데이터를 가공하여 뷰에 전달합니다. 뷰와 모델 간의 결합도를 낮춰주는 역할을 한다.
https://youtu.be/LyYRTcyKJIU
전에 한 MVC 예제를 MVP패턴으로 바꾸어 보며 어떻게 구성하는지 정리하였다.
프리젠터 클래스를 생성한 후, 메인 액티비티의 뷰를 변경하는 코드와 모델을 넘겨준다.
뷰를 제어하고 관리할 때에는 viewInterface 에 접근하고
데이터를 관리할 때에는 model 클래스에 접근하면 된다!
이렇게 뷰를 관리하고 필요한 데이터를 가져오거나 넘길 때에 프리젠터를 사용한다.
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()){
//모델에 있는 패스워드 리스트 길이가 4이고, 모델의 비밀번호 체크하는 함수가 참일때.
viewInterface.checkPassWordMessage()
}
}
}
(ViewInterface)
단어의 의미 그대로 뷰의 요소들을 나타내는 클래스나 인터페이스의 집합을 의미한다.
뷰를 관리하는 함수를 정리해놓는 공간이라 생각하면 쉽다.
interface ViewInterface {
fun toastMessage(i : Int)
fun checkPassWordMessage()
//누른 버튼의 숫자와 pw가 맞을 시 띄울 토스트 메세지의 함수.
}
데이터를 가공하는 관리 역할.
class Model {
var password : MutableList<Int> = mutableListOf()
//변형 가능한 password 리스트 생성
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 += 1
}
}
return trueCount == 4
}
}
class MainActivity : AppCompatActivity(), ViewInterface {
private lateinit var binding : ActivityMainBinding
var presenter = Presenter(this)
//this: 현 클래스, 여기선 현 클래스의 ViewInterface를 뜻함.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
//데이터바인딩을 사용해 현재 액티비티 컨텐츠뷰로 설정. 바인딩 -> UI요소와 액티비티 코드를 연결하는 객체가 됨.
binding.mainActivity = this
//데이터 바인딩으로 레이아웃을 변수랑 연결, mainActivity 변수를 현재 액티비티 객체로 설정.
//레이아웃파일 mainActivity를 현재 액티비티 객체와 연결.
}
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
}
}
다음 글은 MVMM 패턴 정리할게요! 여러 패턴들을 어느 상황에 어떻게 적절히 사용할 수 있을지 아는것이 가장 중요한것 같습니다. 아직 저는 바로 판단하기는 힘들지만.. 연습과 실행.