1. Mapping 처리를 하는 이유
- 어떠한 API에서 받아온 데이터를 바로 쓰기엔 의존성 문제가 생기기 때문에 약하게 해주어야 함 (clean architeture의 원칙_solid)
- 의존성(=결합)을 낮추기 위해서 Data > Domain > Ui(Presentation) 구성으로 하여 Mapper라는 확장 함수를 통해 Entity로 변환하여 사용 (변환 된 Entity는 어느 곳에서도 간접하지 않음)
Guide to app architecture | Android Developers
앱 아키텍처 가이드 | Android Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 앱 아키텍처 가이드 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이 가이드에는 고품질의 강력한
developer.android.com
https://velog.io/@lyh990517/Android-Clean-Architecture-들여다보기
[Android] Clean Architecture 들여다보기
클린아키텍처란 Presentation - Domain - Data각 레이어가 역할이 명확히 구분되어 분리된 아키텍처입니다.
velog.io
2. Data > Domain (Google Places API를 통한 예시)
- google place API에서 받아온 data
@Parcelize
data class GooglePlace(
@SerializedName("html_attributions")
//사용자에게 표시되어야 하는 이 목록
val htmlAttributions: List<String>,
@SerializedName("next_page_token")
//최대20개 사용할수있는 토큰
val nextPageToken: String,
//장소검색
val results: List<ResultReponse>,
//요청이 실패한 이유를 추적
val status: String
): Parcelable
- GooglePlacesEntity.kt 생성
- Entity는 어느 곳에서 간섭을 받으면 안되므로 <ResultResponse> 에서 새로만든 <ResultEntity> 로 변경하여 <ResultResponse>를 가져옴으로써 import 된 것을 삭제
data class GooglePlacesEntity(
val htmlAttributions: List<String>,
val nextPageToken: String,
//val results: List<ResultResponse> -> <ResultEntity>
val results: List<ResultEntity>,
val status: String
)
data class ResultEntity()
- Mapper.kt 생성
- 확장 함수인 toEntity()를 사용하여 해당 클래스를 Mapping 처리
- this.result는 GooglePlace 안에 List 형태로 있기 때문에 map{} 을 사용
fun GooglePlace.toEntity():GooglePlacesEntity{
return GooglePlacesEntity(
this.htmlAttributions,
this.nextPageToken,
//this.results -> this.results.map {resultReponse -> resultReponse.toEntity()}
this.results.map { resultReponse -> resultReponse.toEntity() },
this.status)
}
- Entity에 GooglePlace가 import 가 되지 않는 것이 중요하기 때문에 에러나는 부분을 확인하면서 같은 작업을 반복
더보기
- GooglePlacesEntity.kt
data class GooglePlacesEntity(
val htmlAttributions: List<String>,
val nextPageToken: String,
//val results: List<ResultResponse>
//-> <ResultEntity> 사용을 위해 data class ResultEntity 생성
val results: List<ResultEntity>,
val status: String
)
data class ResultEntity(
val businessStatus: String,
//val geometry: Geometry -> val geometry: GeometryEntity
val geometry: GeometryEntity,
val icon: String,
val iconBackgroundColor: String,
val iconMaskBaseUri: String,
val name: String,
//val openingHours: OpeningHours -> val openingHours: OpeningHoursEntity
val openingHours: OpeningHoursEntity,
// val photos:<Photo> -> val photos:List<PhotoEntity>
val photos: List<PhotoEntity>,
val placeId: String,
//val plusCode: PlusCode -> val plusCode: PlusCodeEntity
val plusCode: PlusCodeEntity,
val priceLevel: Int,
val rating: Double,
val reference: String,
val scope: String,
val types: List<String>,
val userRatingsTotal: Int,
val vicinity: String
)
data class PhotoEntity(
...
)
data class PlusCodeEntity(
...
)
data class GeometryEntity(
...
)
data class OpeningHoursEntity(
...
)
- Mapper.kt
fun GooglePlace.toEntity():GooglePlacesEntity{
return GooglePlacesEntity(this.htmlAttributions, this.nextPageToken, this.results.map { resultReponse -> resultReponse.toEntity() } , this.status)
}
fun ResultReponse.toEntity(): ResultEntity {
return ResultEntity(this.businessStatus, geometry.toEntity(), icon, iconBackgroundColor, iconMaskBaseUri, name, openingHours.toEntity(), photos.map { it.toEntity() }, placeId, plusCode.toEntity(), priceLevel, rating, reference, scope, types, userRatingsTotal, vicinity)
}
/*
ptotos 또한 list 형태이기 때문에 map{}
plusCode는 API에서 받아온 다른 data class를 따르기 때문에 toEntity() 사용
this 생략 가능
*/
fun Photo.toEntity() : PhotoEntity{
return PhotoEntity(height, htmlAttributions, photoReference, width)
}
fun Geometry.toEntity() : GeometryEntity{
return GeometryEntity(location.toEntity(), viewport)
}
...
3. Domain > Ui (Google Places API를 통한 예시)
- GooglePlacesModel.kt 와 domain에서 사용하는 Mapper.kt 를 생성하여 2번 제목과 같은 작업 실시
더보기
- GooglePlacesModel.kt
data class GooglePlacesModel(
val htmlAttributions: List<String>,
val nextPageToken: String,
//val results: List<ResultEntity> -> val results: List<ResultModel>
//data class ResultModel 생성
val results: List<ResultModel>,
val status: String
)
data class ResultModel(
val businessStatus: String,
val icon: String,
val iconBackgroundColor: String,
val iconMaskBaseUri: String,
val name: String,
//val openingHours: OpeningHoursEntity -> val openingHours: OpeningHoursModel
val openingHours: OpeningHoursModel,
//val photos: List<PhotoEntity> -> val photos: List<PhotoModel>
val photos: List<PhotoModel>,
val placeId: String,
val priceLevel: Int,
val rating: Double,
val types: List<String>,
val userRatingsTotal: Int,
)
data class PhotoModel(
val height: Int,
val htmlAttributions: List<String>,
val photoReference: String,
val width: Int
)
data class OpeningHoursModel(
val openNow: Boolean
)
...
- Mapper.kt
fun GooglePlacesEntity.toModel() = GooglePlacesModel(
htmlAttributions, nextPageToken, results, status
)
fun ResultEntity.toModel() = ResultModel(
businessStatus, icon, iconBackgroundColor, iconMaskBaseUri, name, openingHours.toModel(),
photos, placeId, priceLevel, rating, types, userRatingsTotal
)
fun PhotoEntity.toModel() = PhotoModel(
height, htmlAttributions, photoReference, width
)
fun OpeningHoursEntity.toModel() = OpeningHoursModel(
openNow
)
...
- List 형태는 List에 대한 확장 함수를 따로 생성
fun GooglePlacesEntity.toModel() = GooglePlacesModel(
htmlAttributions, nextPageToken, results.toModelResult(), status
)
fun List<ResultEntity>.toModelResult(): List<ResultModel> {
return map {
ResultModel(
it.businessStatus,
it.icon,
it.iconMaskBaseUri,
it.iconBackgroundColor,
it.name,
it.openingHours.toModel(),
it.photos.toModelPhoto(),
it.placeId,
it.priceLevel,
it.rating,
it.types,
it.userRatingsTotal
)
}
}
'Android' 카테고리의 다른 글
Android Studio_ 13. EditText 다루기 (0) | 2024.06.12 |
---|---|
Android Studio_ 12. Google Places(New) API 사용하기 (1) | 2024.06.06 |
Android Studio_ 10. 구글 지도앱 만들기 (0) | 2024.05.30 |
Android Studio_ 0-3. Guideline, Barrier, ViewGroup (0) | 2024.04.30 |
Android Studio_ 9. Figma(피그마)에서 이미지 추출해서 사용하기 (0) | 2024.04.24 |