Skip to content

Instantly share code, notes, and snippets.

View LukaKordic's full-sized avatar

Luka Kordić LukaKordic

View GitHub Profile
class WeatherRepositoryImpl(private val weatherApi: WeatherApi,
private val weatherDao: WeatherDao) : BaseRepository<WeatherInfo, WeatherEntity>(), WeatherRepository {
override suspend fun getWeatherForLocation(location: String): Result<WeatherInfo> {
return fetchData(
apiDataProvider = {
weatherApi.getWeatherForLocation(location).getData(
fetchFromCacheAction = { weatherDao.getWeatherInfoForCity(location) },
cacheAction = { weatherDao.saveWeatherInfo(it) })
},
dbDataProvider = { weatherDao.getWeatherInfoForCity(location) }
interface WeatherApi {
@GET("weather")
suspend fun getWeatherForLocation(@Query("q") location: String, @Query("appid") apiKey: String = API_KEY): Response<WeatherInfoResponse>
}
@Dao
interface WeatherDao {
@Transaction
suspend fun updateWeatherAndReturn(weather: WeatherEntity): WeatherEntity {
saveWeatherInfo(weather)
return getWeatherInfoForCity(weather.name ?: "")
}
@Insert(onConflict = OnConflictStrategy.REPLACE)
sealed class Result<out T : Any>
data class Success<out T : Any>(val data: T) : Result<T>()
data class Failure(val httpError: HttpError) : Result<Nothing>()
class HttpError(val throwable: Throwable, val errorCode: Int = 0)
inline fun <T : Any> Result<T>.onSuccess(action: (T) -> Unit): Result<T> {
if (this is Success) action(data)
return this
}
class GetWeatherUseCaseImpl(private val weatherRepository: WeatherRepository) : GetWeatherUseCase {
override suspend operator fun invoke(location: String) = weatherRepository.getWeatherForLocation(location)
}
interface WeatherApi {
@GET("weather")
suspend fun getWeatherForLocation(@Query("q") location: String, @Query("appid") apiKey: String = API_KEY): Response<WeatherInfoResponse>
}
data class WeatherInfoResponse(val id: Int? = 0,
val weather: List<Weather>?,
val main: MainInfo?,
val name: String? = "") : RoomMapper<WeatherEntity> {
override fun mapToRoomEntity() = WeatherEntity(id ?: 0, weather ?: emptyList(), main ?: MainInfo(), name)
}
data class MainInfo(val temp: Double? = 0.0,
val pressure: Double? = 0.0,
val humidity: Int? = 0)
@Entity(tableName = WEATHER_TABLE_NAME)
data class WeatherEntity(@PrimaryKey val id: Int? = 0,
val weather: ArrayList<Weather>?,
@Embedded
val main: MainInfo?,
val name: String? = "") : DomainMapper<WeatherInfo> {
override fun mapToDomainModel() = WeatherInfo(main?.temp ?: 0.0, main?.humidity ?: 0, main?.pressure ?: 0.0)
}
data class WeatherInfo(val temperature: Double, val humidity: Int, val pressure: Double)
class WeatherViewModel(private val getWeather: GetWeatherUseCase) : BaseViewModel<WeatherInfo, WeatherViewEffects>() {
fun getWeatherForLocation(location: String = DEFAULT_CITY_NAME) = executeUseCase {
getWeather(location)
.onSuccess { _viewState.value = Success(it) }
.onFailure { _viewState.value = Error(it.throwable) }
}
}