티스토리 뷰
이번주 스터디에서는 MVVM패턴 공부를 시작했다
MVVM 패턴
구조
- View : 사용자와 상호작용하는 UI, 데이터 변화 감지를 위한 옵저버를 가짐 (ex. Activity, Fragment)
- Model : 앱에서 사용하는 데이터와 그 데이터를 처리(통신)하는 역할 (ex. dataClass, Repository)
- Repository : 데이터 API를 가지는 클래스, 뷰모델은 DB에 직접 접근하지 않고 repository에 접근하여 앱의 데이터를 관리
- View Model : 뷰와 모델 사이의 인터페이스, 데이터바인딩을 전달하며 뷰를 그리기 위한 데이터를 처리하는 역할
- Live Data : 관찰이 가능한(Observable) 데이터 홀더 클래스, 데이터가 변경될때마다 내부적으로 자동으로 알려줌
동작
- View를 통해 사용자 action을 받는다.
- View는 View Model로 action을 전달한다.
- View Model에서 비지니스 로직을 수행한다.
- View Model은 Model에게 데이터를 요청한다.
- Model은 View Model의 요청에 응답한다.
- View Model은 응답받은 데이터를 가공하고 저장한다.
- View Model은 Data Binding을 통해 View를 수정한다
Repository 패턴 적용
- 필요한 데이터를 처리하는 부분을 비지니스 로직에서 분리시키기 위해 사용되는 디자인 패턴
폴더링
- 얼리버디의 기존 회원가입 코드를 수정
- data폴더 안에 datasource와 repository라는 두개의 폴더를 가진다.
- data/datasource/model 폴더는 통신에 필요한 data class를 가진다
- data/datasource/remote/retrofit 폴더는 기존에 쓰던 networkService코드를 가진다.
- data/datasource/remote 폴더는 인터페이스를 정의하는 RemoteDataSource와 인터페이스를 구현하는 RemoteDataSourceImpl을 가진다.
- data/repository 폴더는 앱의 데이터를 관리하는 repository 클래스들을 가진다.
RemoteDataSource
interface RemoteDataSource { //필요한 함수들을 모아서 정의하는 인터페이스
fun signUp(jsonObject: JsonObject, //post에 필요한 값을 보낼 body
onResponse: (Response<PostSignUpData>) -> Unit, //통신 성공시 수행할 함수
onFailure: (Throwable) -> Unit) //통신 실패시 수행할 함수
}
RemoteDataSourceImpl
class RemoteDataSourceImpl: RemoteDataSource { //RemoteDataSource를 상속받는 클래스
override fun signUp(
jsonObject: JsonObject,
onResponse: (Response<PostSignUpData>) -> Unit,
onFailure: (Throwable) -> Unit
) {
SignUpServiceImpl.SERVICE.postSignUpData(jsonObject).enqueue(object : //enqueue 함수 실행
Callback<PostSignUpData> {
override fun onFailure(call: Call<PostSignUpData>, t: Throwable) { //통신 실패시 실행되는 함수 구현
onFailure(t)
}
override fun onResponse( //통신 성공시 실행되는 함수 구현
call: Call<PostSignUpData>,
response: Response<PostSignUpData>
) {
onResponse(response)
}
})
}
}
SignUpRepository
class SignUpRepository {
val retrofitRemoteDataSource: RemoteDataSource = RemoteDataSourceImpl() //인스턴스 생성
fun signUp(
jsonObject: JsonObject,
onResponse: (Response<PostSignUpData>) -> Unit,
onFailure: (Throwable) -> Unit
){
//생성한 인스턴스로 RempteDataSourceImpl에 구현해놓은 함수 실행
retrofitRemoteDataSource.signUp(jsonObject, onResponse, onFailure)
}
}
SignUpActivity
val signUpRepository = SignUpRepository()
signUpRepository.signUp(jsonObject = body,
onResponse = { //고차함수로 구현, it으로 response에 바로 접근 가능
if (it.isSuccessful){
val intent = Intent(this@MainActivity, SuccessActivity::class.java)
startActivity(intent)
}else
Log.e("postUserData 응답 실패 : ", it.message())
}, onFailure = { //고차함수로 구현, it으로 t에 바로 접근 가능
Log.e("통신 실패 error : ", it.toString())
}
)
동작
- SignUpActivity에서 repository클래스의 인스턴스 생성 후 repository에 구현되어 있는 함수 호출
- SignUpRepository에 들어가 RemoteDataSource 인터페이스 타입의 인스턴스 생성 후 RemoteDataSource에 구현되어 있는 함수 호출
- RemoteDataSource 인터페이스를 상속받아 구현하는 RemoteDataSourceImpl로 들어가 구현된 함수 실행
- SignUpServiceImpl 클래스의 SERVICE객체로 통신 함수를 실행
참고자료🕊
'Android' 카테고리의 다른 글
[디자인패턴] MVVM패턴 (DataBinding) (0) | 2020.03.30 |
---|---|
[kotlin] 안드버디 스터디 정리 -2 (0) | 2020.03.22 |
[kotlin] 코틀린을 코틀린답게 (라이브러리 - 스트림 함수,범위 지정 함수) (0) | 2020.03.08 |
[kotlin] 코틀린을 코틀린답게 (라이브러리 - 조건 확인 함수,컬렉션 생성 함수) (0) | 2020.03.08 |
[kotlin] 안드버디 스터디 정리 - 1 (0) | 2020.03.05 |