⭐️ 기존 방식
Modeling Retrofit Responses With Sealed Classes and Coroutines
@HiltViewModel
class MainViewModel @Inject constructor(
private val userInfoRepository: UserInfoRepository
) {
fun getUserData() {
viewModelScope.launch(Dispatchers.IO) {
mainRepository.getUserData().collect { result ->
when (result) {
is NetworkResult.Success -> {
hideProgress()
}
is NetworkResult.Error -> {
hideProgress()
}
is NetworkResult.Error -> {
showProgress()
}
}
}
}
}
fun getProfileData() {
viewModelScope.launch(Dispatchers.IO) {
mainRepository.getProfile().collect { result ->
when (result) {
is NetworkResult.Success -> {
hideProgress()
}
is NetworkResult.Error -> {
hideProgress()
}
is NetworkResult.Error -> {
showProgress()
}
}
}
}
}
}
class UserInfoRepository @Inject constructor(
private val userApiService: UserApiService
) : Repository {
fun getUserData() = flow {
emit(NetworkResult.Loading)
emit(safeApiCall{ userApiService.getUserData() })
}
fun getProfileData() = flow {
emit(NetworkResult.Loading)
emit(safeApiCall{ userApiService.getProfileData() })
}
}
sealed class NetworkResult<T : Any> {
data class Success<T: Any>(val data: T) : NetworkResult<T>()
data class Error<T: Any>(val code: Int, val message: String?) : NetworkResult<T>()
object Loading : NetworkResult<Nothing>()
}
suspend fun <T> safeApiCall (
execute: suspend () -> Response<T>
): NetworkResult<T> {
return try {
val response = execute()
val body = response.body()
if (response.isSuccessful && body != null) {
return NetworkResult.Success(body)
} else {
return NetworkResult.Error(code = response.code(), message = response.message())
}
} catch (e: HttpException) {
return NetworkResult.Error(code = e.code(), message = e.message())
} catch (e: Throwable) {
return NetworkResult.Error(null, e.message ?: e.toString())
}
}
👩🏻💻 구조 설명
🤔 생각해볼점