[Android] UserListApp - Data Part - Part3
Tags: android, kotlin, retrofit, api
Published: 2023-06-13 09:46:53

#Remote Info
[https://random-data-api.com/documentation](https://random-data-api.com/documentation)
##Response Data is 

![Data Type](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tn22hjazvaldkn505f0x.png)

##Create UserDto
Not create all data type .
```
data class UserDto(
    val id : Int ,
    val username : String ,
    val gender : String ,
    val phone_number : String ,
    val date_of_birth : String,
    val email : String,
    val avatar : String,
    val address: Address,
)

```

```
data class Address(
    val city: String,
    val coordinates: Coordinates,
    val country: String,
    val state: String,
    val street_address: String,
    val street_name: String,
    val zip_code: String
)
data class Coordinates(
    val lat: Double,
    val lng: Double
)

```
##Create Remote API Interface UserApi

```
interface UserApi {

    @GET("users")
    suspend fun getRandomUser() : Response<UserDto>

    @GET("users")
    suspend fun getUserBySize(
        @Query("size") size : String,
    ) : Response<List<UserDto>>

    companion object{
        const val BASE_URL = "https://random-data-api.com/api/v2/"
    }

}
```
##Create Mapper

```
fun UserDto.toUser() : User {
    return User(
        id= id,
        username = username,
        gender = gender,
        phoneNumber = phone_number,
        dateOfBirth = date_of_birth,
        email = email,
        avatar = avatar,
        lat = address.coordinates.lat,
        lng = address.coordinates.lng
    )
}
```
##Create Custom Result Class Resource.kt

```
sealed class Resource<T>(val data : T?=null , val message : String ?=null){
    class Loading<T>(data: T? = null) : Resource<T>(data)
    class Error<T>(data: T? = null , message: String?) : Resource<T>(data,message)
    class Success<T>(data: T?) : Resource<T>(data)
}
```
##Create Domain Repository UserRepository
這個UserRepository裡面的資料一定是User，因為要在App內使用的
所以在實作那層會有一個Mapper去做轉換(domain>util>UserMapper.kt)

```
interface UserRepository {

    suspend fun getRandomUser(): Flow<Resource<User>>

    suspend fun getUserBySize(size : String) : Flow<Resource<List<User>>>
}
```
##Create Data Repository UserRepositoryImpl

```
class UserRepositoryImpl(
    private val userApi: UserApi
) : UserRepository{

    override suspend fun getRandomUser(): Flow<Resource<User>> = flow{
       emit(Resource.Loading())
        try {
            val result = userApi.getRandomUser()
            if (result.isSuccessful){
                result.body()?.let {
                    emit(
                        Resource.Success(it.toUser())
                    )
                }
            }else{
                emit(
                    Resource.Error(
                        data = null,
                        message = "${result.errorBody()?.string()}"
                    )
                )
            }
        }catch (e : IOException){
            emit(
                Resource.Error(
                    data = null,
                    message = "IOE Error"
                )
            )
        }

    }

    override suspend fun getUserBySize(size: String): Flow<Resource<List<User>>> = flow{
        emit(
            Resource.Loading()
        )
        try {
            val result = userApi.getUserBySize(size)
            if (result.isSuccessful){
                result.body()?.let {
                    it.let {
                        emit(
                            Resource.Success(
                                data =it.map { userDto ->
                                    userDto.toUser()
                                }
                            )
                        )
                    }
                }
            }else{
                emit(
                    Resource.Error(
                        data = emptyList(),
                        message = result.errorBody()?.string()
                    )
                )
            }
        }catch (e : IOException){
            emit(
                Resource.Error(
                    data = null,
                    message = e.message
                )
            )
        }
    }
}
```