Model View Presenter 패턴을 줄여 말해 MVP 패턴이라고 합니다.
MVC 패턴에서 Model 와 View의 의존성이 높아 유지보수가 어렵다는 단점을 보완하여 만든것이 MVP 패턴입니다.
아래에 이해를 돕기 위해 이미지를 첨부하겠습니다.
일단 시작전 전 Android 앱 개발자 임으로 아래를 사용했습니다.
이정도 입니다. 그럼 가봅시다
// Log
implementation 'com.jakewharton.timber:timber:5.0.1'
//Layout
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
//Firebase
implementation(platform("com.google.firebase:firebase-bom:32.2.0"))
implementation("com.google.firebase:firebase-analytics-ktx")
implementation("com.google.firebase:firebase-crashlytics-ktx")
implementation("com.google.firebase:firebase-database-ktx")
위에서 부터 설명하자면
Contract라는 클래스를 선언해 해당 이벤트가 끝났을때 데이터를 view로 넘겨주기 위하여 interface으로 만들어 클래스를 만들엇습니다.
interface Contract {
interface View{
fun showSignUpResult(message: String)
fun showLoading()
}
interface Presenter{
fun requestSignUp(userData : UserInfo)
}
}
class SignUpActivity : AppCompatActivity() , Contract.View{
private var _binding : ActivitySignUpBinding ?= null
private val binding get() = _binding!!
private lateinit var presenter : SignUpPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivitySignUpBinding.inflate(layoutInflater)
setContentView(binding.root)
init()
addListener()
}
private fun init(){
presenter = SignUpPresenter(this)
}
private fun addListener(){
binding.btnSignUp.setOnClickListener {
val id = binding.editId.text.toString().replace(" ","")
val password = binding.editPassword.text.toString().replace(" ","")
val phoneNumber = binding.editPhoneNumber.text.toString().replace(" ","")
val nickName = binding.editNickName.text.toString().replace(" ","")
if(id == "" || password == "" || phoneNumber == "" || nickName == ""){
Toast.makeText(this , getString(R.string.msg_input_data) , Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
val data = UserInfo(id , password , phoneNumber , nickName)
presenter.requestAlreadySignUp(data)
}
}
override fun onDestroy() {
super.onDestroy()
_binding = null
}
override fun showSignUpResult(message: String) {
Timber.d("The data is Come")
}
override fun showLoading() {
Timber.d("Loading for signUp")
}
}
interface 에 View 을 implement 해서 function 을 override 을 해서 사용합니다 .
그후 Init 에서 presenter = SignUpPresenter(this) 을 해 Presenter 을 사용합니다.
class SignUpPresenter(private val view : Contract.View) : FirebaseDataListener , Contract.Presenter{
private val dataManager: FirebaseDataManger = FirebaseDataManger()
fun requestAlreadySignUp(data : UserInfo){
view.showLoading()
dataManager.readUserInfo(data.phoneNumber , this )
}
override fun onMessageIsCome(data: UserInfo) {
Timber.d("Success to get UserInfo $data")
}
override fun onMessageIsFail(message: String) {
Timber.d("Success to get UserInfo $message")
}
override fun requestSignUp(userData: UserInfo) {
//아직 미구현
}
}
interface FirebaseDataListener {
fun onMessageIsCome(data: UserInfo)
fun onMessageIsFail(message: String)
}
Model(Firebase database 조회) 하기 전에 해당 데이터는 비동기 적으로 오기 떄문에 데이터가 오면 Listner 을 하기 위해 선언했습니다.
class FirebaseDataManger {
private var database = Firebase.database(BuildConfig.FIREBASE_DATABASE_URL)
fun readUserInfo(phoneNumber : String , listener : FirebaseDataListener){
val url = BuildConfig.userInfo+"/"+phoneNumber
database.getReference(url).addListenerForSingleValueEvent(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
val value = snapshot.getValue<UserInfo>()
if(value == null){
listener.onMessageIsFail("error to get Message")
return
}
listener.onMessageIsCome(value)
Timber.d("Success to get Firebase Database $value")
}
override fun onCancelled(error: DatabaseError) {
Timber.d("Fail to get Firebase Database")
listener.onMessageIsFail(error.message)
}
})
}
}
그후 Firebase에서 데이터를 가져오는 것 구현합니다.
참고로 Firebase Realtime database 은 url에 / 가 꼭 붙어야 합니다. 안붙으면 아무것도 안옵니다.
예를들어 runningProject/realtimeDatabase/userInfo 해야 데이터를 Return 합니다.
그후 인자로 받은 listener 을 통해 메세지를 return 해줍니다.
그럼 다시 Presneter 로 가보겠습니다.
class SignUpPresenter(private val view : Contract.View) : FirebaseDataListener , Contract.Presenter{
private val dataManager: FirebaseDataManger = FirebaseDataManger()
fun requestAlreadySignUp(data : UserInfo){
view.showLoading()
dataManager.readUserInfo(data.phoneNumber , this )
}
override fun onMessageIsCome(data: UserInfo) {
Timber.d("Success to get UserInfo $data")
}
override fun onMessageIsFail(message: String) {
Timber.d("Success to get UserInfo $message")
}
override fun requestSignUp(userData: UserInfo) {
//아직 미구현
}
}
그후 onMessage을 통해 해당 값을 return 받을수 있겠지요
그후 인자로 받은 view을 통해 호출하면 view에 해당 값을 reutrn 해줄수 있습니다.
그럼 오늘도 읽어주셔서 감사합니다
-피드백와 비판은 언제나 환영입니다-