Skip to content

Instantly share code, notes, and snippets.

View LukaKordic's full-sized avatar

Luka Kordić LukaKordic

View GitHub Profile
abstract class BaseViewModel<T : Any, E> : ViewModel(), KoinComponent {
protected val coroutineContext: CoroutineContextProvider by inject()
private val connectivity: Connectivity by inject()
protected val _viewState = MutableLiveData<ViewState<T>>()
val viewState: LiveData<ViewState<T>>
get() = _viewState
protected val _viewEffects = MutableLiveData<E>()
/**
* Use this if you need to cache data after fetching it from the api, or retrieve something from cache
*/
inline fun <T : RoomMapper<R>, R : DomainMapper<U>, U : Any> Response<T>.getData(
cacheAction: (R) -> Unit,
fetchFromCacheAction: () -> R): Result<U> {
try {
onSuccess {
val databaseEntity = it.mapToRoomEntity()
abstract class BaseRepository<T : Any, R : DomainMapper<T>> : KoinComponent {
private val connectivity: Connectivity by inject()
private val contextProvider: CoroutineContextProvider by inject()
/**
* Use this if you need to cache data after fetching it from the api, or retrieve something from cache
*/
protected suspend fun fetchData(
apiDataProvider: suspend () -> Result<T>,
dbDataProvider: suspend () -> R
class WeatherFragment : BaseFragment() {
private val viewModel: WeatherViewModel by viewModel()
override fun getLayout() = R.layout.fragment_weather
override fun viewReady() {
viewModel.getWeatherForLocation()
subscribeToData()
sealed class ViewState<out T : Any>
class Success<out T : Any>(val data: T) : ViewState<T>()
class Error<out T : Any>(val error: Throwable) : ViewState<T>()
class Loading<out T : Any> : ViewState<T>()
class NoInternetState<T : Any> : ViewState<T>()
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) }
}
}
data class WeatherInfo(val temperature: Double, val humidity: Int, val pressure: Double)
@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 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)
interface WeatherApi {
@GET("weather")
suspend fun getWeatherForLocation(@Query("q") location: String, @Query("appid") apiKey: String = API_KEY): Response<WeatherInfoResponse>
}