-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/#7 week4 #8
base: develop
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ํต์ฐ ์์ธ์ ์ฌ์ํ ๊ฒ๋ ์ฒ๋ฆฌํ์ ๊ณผ์ ์ ์ ๋ณผ ์ ์๋ ์ฝ๋์์ต๋๋ค..!
hilt ์ ๋ํด ๋ช
ํํ ์ง์์ด ์๋ค๊ณ ์๊ฐํ๋๋ฐ, ํจ์๋ ์ฝ๋ ๋ณด๊ณ ๋ง์ด ๋ฐฐ์ธ ์ ์๋ ๊ธฐํ์์ต๋๋ค. ๊ฐ ๋ ์ด์ด์ ๋ช
์ํ ๋ถ๋ถ๋ค ๋ค์ ํ๋ฒ ์ฐธ๊ณ ํด๋ณด๊ฒ ์ต๋๋ค!
hilt-core = { group = "com.google.dagger", name = "hilt-core", version.ref = "hilt" } | ||
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" } | ||
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } | ||
hilt-android-testing = { group = "com.google.dagger", name = "hilt-android-testing", version.ref = "hilt" } | ||
hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } | ||
hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } | ||
hilt-manager = {group = "androidx.hilt" , name = "hilt-compiler", version.ref = "hiltManager"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hilt ์ฃผ์ ์ ์ฌ์ฉํ์ จ๋ค์! ์ ๋ ์ด๋ฒ ๊ณผ์ ์์ ์ฌ์ฉํด๋ณด๋ ค๋ค๊ฐ, ๋ช ํํ ์ง์์ด ์๋ ๊ฒ ๊ฐ์ ๋ฆฌํฉํ ๋ง ๊ฐ ์งํํด๋ณด๋ ๊ฒ์ผ๋ก ํ์์ต๋๋ค..! ํจ์๋ ์ฝ๋๋ณด๊ณ ํ๋ํ๋ ์ดํดํด๋ณด๋๋ก ํ ๊ฒ์!
@Serializable | ||
data class BaseResponse<T>( | ||
@SerialName("result") | ||
val result: T? = null, | ||
@SerialName("code") | ||
val code: String? = null, | ||
@SerialName("error") | ||
val error: BaseError? = null, | ||
) { | ||
@Serializable | ||
data class BaseError( | ||
@SerialName("code") | ||
val code: Int, | ||
@SerialName("message") | ||
val message: String, | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๊ณตํต๋๋ response๋ฅผ BaseResponse๋ก ๋๊ณ , T๋ฅผ ์ฌ์ฉํด์ ํด๋น ํ๋์ ๋ฐ๋ result ๊ฐ์ ์ ์ํ ๊ฒ ์ด๊ตฐ์! ์ฐธ๊ณ ํ๊ฒ ์ต๋๋น
fun LoginInfo.toRequestLogin(): RequestLoginDto = RequestLoginDto( | ||
userName = this.userName, | ||
password = this.password | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ ์ domain์ ๋ํ ์ง์์ด ๋ช ํํ์ง ์์๋๋ฐ, ์ด ์ฝ๋์ฒ๋ผ ์๋ฒ์์ ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ํด๋ผ์ด์ธํธ์์ ๋ง๋ ๋ฐ์ดํฐ (์๋ฅผ ๋ค๋ฉด ๋ฐ์ดํฐ ํด๋์ค๋ก ์ ์)๋ก ๊ฐ๊ณตํด์ฃผ๋ ์ญํ ์ด๋ผ๊ณ ์๊ฐํ๋ฉด ๋ ๊น์?
fun ResponseLoginDto.toResponseLoginModel(): ResponseLoginModel = ResponseLoginModel( | ||
token = this.token | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
viewModel์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ๋ผ์ฐ๋ ๋ฐฉ๋ฒ๋ ์๊ตฐ์..! State๊ฐ์ ๊ฒ์ ์ฌ์ฉํ๋ฉด ๋ฐ๋ก ๋ณ๊ฒฝ์ด ๋๊ฒ ๋ค์!
sealed class Error(message: String?) : Exception(message) { | ||
data class ApiError( | ||
val errorMessage: String?, | ||
) : Error(errorMessage) | ||
|
||
data class NetWorkConnectError( | ||
val errorMessage: String, | ||
) : Error(errorMessage) | ||
|
||
data class TimeOutError( | ||
val errorMessage: String, | ||
) : Error(errorMessage) | ||
|
||
data class UnknownError( | ||
val errorMessage: String, | ||
) : Error(errorMessage) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๊ฐ ์๋ฌ ์ ๋ฆฌ์ ์ ์ฑ์ด ๋ณด์ ๋๋ค..1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ง์ง ์ ์ฑ ๊ตฟ๊ตฟ....๐๐ป๐๐ป๐๐ป
private const val UNKNOWN_ERROR_MESSAGE = "Unknown error" | ||
private const val NETWORK_CONNECT_ERROR_MESSAGE = "๋คํธ์ํฌ ์ฐ๊ฒฐ์ด ์ํํ์ง ์์ต๋๋ค" | ||
private const val INTERNET_CONNECTION_ERROR_MESSAGE = "์ธํฐ๋ท์ ์ฐ๊ฒฐํด ์ฃผ์ธ์" | ||
private const val TIMEOUT_ERROR_MESSAGE = "์๋ฒ๊ฐ ์๋ตํ์ง ์์ต๋๋ค" | ||
private const val NULL_ERROR_MESSAGE = "error message is null" | ||
|
||
private fun HttpException.getErrorMessage(): String { | ||
val errorBody = response()?.errorBody()?.string() ?: return UNKNOWN_ERROR_MESSAGE | ||
return parseErrorMessage(errorBody) | ||
} | ||
|
||
private fun parseErrorMessage(errorBody: String): String = | ||
try { | ||
val errorResponse = Json.decodeFromString<BaseResponse<BaseResponse.BaseError>>(errorBody) | ||
errorResponse.error?.message ?: NULL_ERROR_MESSAGE | ||
} catch (e: Exception) { | ||
UNKNOWN_ERROR_MESSAGE | ||
} | ||
|
||
fun Throwable.toCustomError(): Throwable = when (this) { | ||
is HttpException -> Error.ApiError(this.getErrorMessage()) | ||
is UnknownHostException -> Error.NetWorkConnectError(NETWORK_CONNECT_ERROR_MESSAGE) | ||
is ConnectException -> Error.NetWorkConnectError(INTERNET_CONNECTION_ERROR_MESSAGE) | ||
is SocketTimeoutException -> Error.TimeOutError(TIMEOUT_ERROR_MESSAGE) | ||
else -> Error.UnknownError(this.message ?: UNKNOWN_ERROR_MESSAGE) | ||
} | ||
|
||
fun <T> Throwable.handleThrowable(): Result<T> = Result.failure(this.toCustomError()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
api ๋ช ์ธ์ ๋ช ์๋ ์ค๋ฅ ๋ฟ ์๋๋ผ ํด๋ผ์ด์ธํธ์ ๊ทธ ์ธ ๋ฐ์ํ๋ ์ค๋ฅ์ ๋ํ ์ ์๋ฅผ ์ด๋ ๊ฒ ํ ์๋ ์๊ตฐ์
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4์ฃผ์ฐจ ๊ณผ์ ์ํํ๋๋ผ ๊ณ ์ ๋ง์ผ์ จ์ต๋๋ค!! ๋งค์ฃผ ์ฝ๋ฆฌ์กฐ์ฅ๋ ์ฝ๋ ๋ฆฌ๋ทฐํ๋ฉด์ ๋ง์ด ๋ฐฐ์๊ฐ ์ ์์ด์ ์ ์ตํฉ๋๋ค. ํฉ์ธ๋ ํ์ดํ ์ ๋๋ค!!
package org.sopt.and | ||
|
||
sealed interface UiState<out T> { | ||
data object Empty : UiState<Nothing> | ||
|
||
data object Loading : UiState<Nothing> | ||
|
||
data class Success<T>( | ||
val data: T, | ||
) : UiState<T> | ||
|
||
data class Failure( | ||
val errorMessage: String, | ||
) : UiState<Nothing> | ||
|
||
fun getUiStateModel(): UiStateModel { | ||
return UiStateModel( | ||
this is Empty, | ||
this is Loading, | ||
this is Success, | ||
this is Failure, | ||
) | ||
} | ||
} | ||
|
||
data class UiStateModel( | ||
val isEmpty: Boolean = false, | ||
val isLoading: Boolean = true, | ||
val isSuccess: Boolean = false, | ||
val isFailure: Boolean = false, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ด๋ ๊ฒ UI State๋ฅผ ๊ด๋ฆฌํ๋ ์ ๋ง ์ดํด๋ ์ฝ๊ณ ์ ์ฉํ๋ค์
package org.sopt.and.data.dto.response | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ResponseLoginDto( | ||
@SerialName("token") | ||
val token: String | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ด๋ฐ ์์ผ๋ก ํ ํฐ๋ Serializableํ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๊ตฌ์กฐํํ๋ฉด, ๋ค๋ฅธ ์ธ์ฆ ๊ด๋ จ ๋ฐ์ดํฐ์ ํจ๊ป ํ์ฅ ๊ฐ๋ฅ์ฑ์ด ์๊ธฐ๊ฒ ๊ตฐ์.
package org.sopt.and.data.service | ||
|
||
import org.sopt.and.data.dto.BaseResponse | ||
import org.sopt.and.data.dto.response.ResponseMyHobbyDto | ||
import retrofit2.Call | ||
import retrofit2.http.GET | ||
import retrofit2.http.Header | ||
|
||
interface MyPageService { | ||
@GET("/user/my-hobby") | ||
suspend fun getMyHobby( | ||
@Header("token") token: String | ||
): BaseResponse<ResponseMyHobbyDto> | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suspend fun์ ์ฒ์๋ณด๋๋ฐ, ๋ ์ง๊ด์ ์ผ๋ก ์์ฑ๋ผ์ ์ข์ ๊ฑฐ ๊ฐ์ต๋๋ค!!
sealed class Error(message: String?) : Exception(message) { | ||
data class ApiError( | ||
val errorMessage: String?, | ||
) : Error(errorMessage) | ||
|
||
data class NetWorkConnectError( | ||
val errorMessage: String, | ||
) : Error(errorMessage) | ||
|
||
data class TimeOutError( | ||
val errorMessage: String, | ||
) : Error(errorMessage) | ||
|
||
data class UnknownError( | ||
val errorMessage: String, | ||
) : Error(errorMessage) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ง์ง ์ ์ฑ ๊ตฟ๊ตฟ....๐๐ป๐๐ป๐๐ป
fun submitLogin(userInfo: LoginInfo) { | ||
viewModelScope.launch { | ||
loginRepository.postLogin(userInfo) | ||
.onSuccess { response -> | ||
_loginState.emit(UiState.Success(response)) | ||
_authToken.emit(response.token) | ||
} | ||
.onFailure { exception -> | ||
_loginState.emit(UiState.Failure("๋ก๊ทธ์ธ ์คํจ")) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
์ฝ๋๋ฆฌ๋ทฐ ํ๋ฉด์ emit๋ ๊ณต๋ถํ๊ฒ ๋๋ค์! ๋๋ถ์ ๋ฐฐ์๊ฐ๋๋ค!
Related issue ๐
Work Description โ๏ธ
Screenshot ๐ธ
4.mp4
Uncompleted Tasks ๐
To Reviewers ๐ข
์.. ๋ ์ข์ ์ฝ๋๊ฐ ๋ถ๋ช ์์ ๊ฒ ๊ฐ์๋ฐ.. ์ข์ ๋ก์ง์ผ๋ก ์ฝ๋๋ฅผ ์งฐ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋คใ ใ ๊ทธ๋ฅ ๋ง๊ตฌ ๋๋ ค์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค ์๋ฒํต์ ์ํ๊ณ ์ํผ์
๋ค๋ค ํฉ์ธ ํ์ดํ !