/**
* Repository 단에서
* UserRequestDTO의 형식을 검증하여 service단으로 넘김
*
*
* Fragment
* UserRequest / UserResponse
* ViewModel
* UserRequestDTO / UserRequestDTO
* Repository
* (LoginRequestDTO , RegisterRequestDTO, ... ) / ( LoginResponseDTO, RegisterRequest, ...)
* Service
* **/
코드의 통일성을 위해서 앱 아키텍처에 따른 각 계층구조에서 사용할 모델을 정리해 보았다.
Fragment에서는 각각의 요청 (로그인 / 회원가입 / 아이디 찾기 / 비밀번호 찾기)에 대해 각각의 DTO 를 사용하여
다음과 같이 ViewModel에 UserRequest 클래스로 요청한다.
loginViewModel.request(
UserRequest.Login(
LoginRequestDTO(
email = binding.username.text.toString(),
password = binding.password.text.toString()
)
)
)
/**
/* 현재 코드는 각 상황별로 직접 UserRequest(UserRequestDTO())로 요청하도록 되어있지만
/* 서버에 요청하는 코드를 UserRequestDTO 형식을 받는 함수로 따로 만들어
/* 해당 함수에서 UserRequestDTO의 형식을 구분하여 UserResponse에 담아 viewModel에 요청하는 역할을 수행하도록 하여
/* 요청하는 부분에서는 단순히 해당 코드를 각각의 DTO에 담아서 요청할 수 있도록 만든다면 가독성측면과 직관성을 보완 할 수 있을 것 같다.
**/
형식을 통해 ViewModel에게 데이터를 요청하고
class LoginActivity{
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loginViewModel.response.observe(this, ::responseObserver )
}
private fun responseObserver(response : UserResponse){
if( loading.isShowing )
loading.dismissWithAnimation()
when(response){
is UserResponse.Login ->{
val dto = response.dto
if(dto.success){
//로그인 성공 시 결과값 표시
}
}
is UserResponse.FindIdPw ->{
val dto = response.dto
if(dto.success) {
//아이디&비밀번호 찾기 성공 시 결과값 표시
}
}
is UserResponse.Register ->{
val dto = response.dto
if(dto.success) {
//회원가입 성공 시 결과값 표시
}
}
}
}
}
ViewModel에서는 reqeust함수로 들어오는 UserRequest의 타입에 따른 요청을
repository에 UserRequestDTO 형식을 사용하여 전송한다.
UserRequestDTO형식을 사용하기 때문에 dto = requestType.dto로 미리 정의하여
_resposne.value = repository.해당함수(dto)와 같이 코드를 통일성있고 간결하게 작성할 수 있었다.
class LoginViewModel : ViewModel() {
val _response = MutableLiveData<UserResponse>()
val response : LiveData<UserResponse> = _response
val request : (UserRequest) -> Unit
init {
request = { requestType ->
val dto = requestType.dto
viewModelScope.launch {
when(requestType){
//로그인
is UserRequest.Login -> {
if ((isUserNameValid(requestType.dto.email) && isPasswordValid(requestType.dto.password))) {
_response.value = repository.login(dto)
}
}
//회원가입
is UserRequest.Register -> {
_response.value = repository.register(dto)
}
//아이디찾기
is UserRequest.FindPW -> {
_response.value = repository.findID(dto)
};
//비밀번호찾기
is UserRequest.FindID -> {
_response.value = repository.findPW(dto)
};
}
}
}
}
}
sealed class UserRequest() {
abstract val dto: UserRequestDTO
data class Login(override val dto : LoginRequestDTO) : UserRequest()
data class FindPW(override val dto : FindPwRequestDTO) : UserRequest()
data class FindID(override val dto : FindIdRequestDTO) : UserRequest()
data class Register(override val dto : RegisterRequestDTO) : UserRequest()
}
sealed class UserResponse{
abstract val dto : UserResponseDTO
data class Login(override val dto : LoginResponseDTO) : UserResponse()
data class FindIdPw(override val dto : FindResponseDTO) : UserResponse()
data class Register(override val dto : SuccessResponse) : UserResponse()
}
다음은 UI 처리 부분이다. Activity는 onCreate에서 response LiveData를 observing하게 한다.
해당 observer에서는 response의 타입을 기준으로 UI에 반영하는 부분만 처리하면 된다.
fun UserRepository() : UserRepository = UserRepositoryImpl()
interface UserRepository {
suspend fun login(dto : UserRequestDTO) : UserResponse
suspend fun register(dto : UserRequestDTO) : UserResponse
suspend fun findID(dto : UserRequestDTO) : UserResponse
suspend fun findPW(dto : UserRequestDTO) : UserResponse
}
private class UserRepositoryImpl: UserRepository {
@Inject
private lateinit var backend : UserService
override suspend fun login(dto: UserRequestDTO): UserResponse {
return withContext(Dispatchers.IO){
//처리코드
}
UserResponse.Login(responseDTO)
}
}
override suspend fun register(dto: UserRequestDTO): UserResponse {
return withContext(Dispatchers.IO) {
//처리코드
UserResponse.Register(responseDTO)
}
}
override suspend fun findID(dto: UserRequestDTO): UserResponse {
return withContext(Dispatchers.IO){
//처리코드
UserResponse.FindIdPw(responseDTO)
}
}
override suspend fun findPW(dto: UserRequestDTO): UserResponse {
return withContext(Dispatchers.IO){
//처리코드
UserResponse.FindIdPw(responseDTO)
}
}
'Android > Feedback on Failures' 카테고리의 다른 글
ErrorCode를 통한 예외처리 구분 (0) | 2023.10.22 |
---|---|
<Refactoring> Retrofit과 데이터 모델 (0) | 2023.09.12 |
<Refactoring> LiveData Observing (0) | 2023.09.10 |
ListAdapter의 submitList UI 반영 문제 (0) | 2023.08.15 |
RecyclerView Item 크기 조절 문제 (0) | 2023.08.11 |