-
Notifications
You must be signed in to change notification settings - Fork 35
Cache and Eviction Strategy: Offline First #41
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
base: develop
Are you sure you want to change the base?
Changes from 15 commits
7756904
6b81d5b
1039d32
58916aa
95d5e42
f113abe
6f50a41
3d761b5
248820e
b47104f
84a4bd1
545579a
92499fd
b6d13ce
20e7cd9
50f9bb5
6e7b82d
67110cc
7f65822
7c5bd6d
1faa9b5
078cfeb
715ca3f
d63ad19
738bda6
64e6c37
101ddb3
8f4f983
8d8a38b
2fdf3c3
97f4dfb
f928492
bf60f85
521a1b8
98335c6
7d8555e
ae05432
710c0ad
09a8f59
06314f4
8b77bb8
e283bb2
12e09e0
e32d492
81f4d4b
c868b82
15c0363
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,22 @@ | ||
| package com.github.odaridavid.weatherapp | ||
|
|
||
| import android.app.Application | ||
| import androidx.hilt.work.HiltWorkerFactory | ||
| import androidx.work.Configuration | ||
| import dagger.hilt.android.HiltAndroidApp | ||
| import timber.log.Timber | ||
| import javax.inject.Inject | ||
|
|
||
| @HiltAndroidApp | ||
| class WeatherApp : Application() | ||
| class WeatherApp : Application(), Configuration.Provider{ | ||
| override fun onCreate() { | ||
| super.onCreate() | ||
| if (BuildConfig.DEBUG) { | ||
| Timber.plant(Timber.DebugTree()) | ||
| } | ||
| } | ||
| @Inject | ||
| lateinit var workerFactory: HiltWorkerFactory | ||
| override fun getWorkManagerConfiguration(): Configuration = | ||
| Configuration.Builder().setWorkerFactory(workerFactory).build() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,11 @@ import com.github.odaridavid.weatherapp.core.model.Temperature | |
| import com.github.odaridavid.weatherapp.core.model.Units | ||
| import com.github.odaridavid.weatherapp.core.model.Weather | ||
| import com.github.odaridavid.weatherapp.core.model.WeatherInfo | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.DailyWeatherEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.HourlyWeatherEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.TemperatureEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.WeatherEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.WeatherInfoResponseEntity | ||
| import java.text.SimpleDateFormat | ||
| import java.util.Date | ||
| import kotlin.math.roundToInt | ||
|
|
@@ -52,6 +57,52 @@ fun TemperatureResponse.toCoreModel(unit: String): Temperature = | |
| min = formatTemperatureValue(min, unit), | ||
| max = formatTemperatureValue(max, unit) | ||
| ) | ||
| fun WeatherEntity.toCoreEntity(unit: String): Weather = | ||
| Weather( | ||
| current = toCurrentWeather(unit = unit), | ||
| hourly = hourly.map { it.toCoreEntity(unit = unit) }, | ||
| daily = daily.map { it.toCoreEntity(unit = unit) } | ||
| ) | ||
| private fun WeatherEntity.toCurrentWeather(unit: String): CurrentWeather = | ||
| CurrentWeather( | ||
| temperature = formatTemperatureValue(temp, unit), | ||
| feelsLike = formatTemperatureValue(feels_like, unit), | ||
| weather = listOf(toWeatherInfo()) | ||
| ) | ||
| private fun WeatherEntity.toWeatherInfo(): WeatherInfo = | ||
| WeatherInfo( | ||
| id = id, | ||
| main = main, | ||
| description = description, | ||
| icon = "${BuildConfig.OPEN_WEATHER_ICONS_URL}[email protected]" | ||
| ) | ||
| fun DailyWeatherEntity.toCoreEntity(unit: String): DailyWeather = | ||
| DailyWeather( | ||
| forecastedTime = getDate(dt,"EEEE dd/M"), | ||
| temperature = temperature.toCoreEntity(unit = unit), | ||
| weather = weather.map { it.toCoreEntity() } | ||
| ) | ||
|
|
||
| fun HourlyWeatherEntity.toCoreEntity(unit: String): HourlyWeather = | ||
| HourlyWeather( | ||
| forecastedTime = getDate(dt,"HH:SS"), | ||
| temperature = formatTemperatureValue(temperature, unit), | ||
| weather = weather.map { it.toCoreEntity() } | ||
| ) | ||
|
|
||
| fun WeatherInfoResponseEntity.toCoreEntity(): WeatherInfo = | ||
| WeatherInfo( | ||
| id = id, | ||
| main = main, | ||
| description = description, | ||
| icon = "${BuildConfig.OPEN_WEATHER_ICONS_URL}[email protected]" | ||
| ) | ||
|
|
||
| fun TemperatureEntity.toCoreEntity(unit: String): Temperature = | ||
| Temperature( | ||
| min = formatTemperatureValue(min, unit), | ||
| max = formatTemperatureValue(max, unit) | ||
| ) | ||
|
|
||
| private fun formatTemperatureValue(temperature: Float, unit: String): String = | ||
| "${temperature.roundToInt()}${getUnitSymbols(unit = unit)}" | ||
|
|
@@ -68,3 +119,56 @@ private fun getDate(utcInMillis: Long, formatPattern: String): String { | |
| val dateFormat = Date(utcInMillis * 1000) | ||
| return sdf.format(dateFormat) | ||
| } | ||
|
|
||
| fun WeatherResponse.toWeatherEntity(): WeatherEntity { | ||
| val currentTime = System.currentTimeMillis() | ||
| val currentWeatherInfo = current.weather.first() | ||
|
|
||
| val hourlyWeatherEntities = hourly.map { hourlyResponse -> | ||
| HourlyWeatherEntity( | ||
| dt = hourlyResponse.forecastedTime, | ||
| temperature = hourlyResponse.temperature, | ||
| weather = hourlyResponse.weather.map { it.toWeatherInfoResponse() } | ||
| ) | ||
| } | ||
|
|
||
| val dailyWeatherEntities = daily.map { dailyResponse -> | ||
| DailyWeatherEntity( | ||
| dt = dailyResponse.forecastedTime, | ||
| temperature = dailyResponse.temperature.toTemperatureEntity(), | ||
| weather = dailyResponse.weather.map { it.toWeatherInfoResponse() } | ||
| ) | ||
| } | ||
|
|
||
| return WeatherEntity( | ||
| dt = currentTime, | ||
| id = 0, | ||
| feels_like = current.feelsLike, | ||
| temp = current.temperature, | ||
| temp_max = current.temperature, | ||
| temp_min = current.temperature, | ||
| description = currentWeatherInfo.description, | ||
| icon = currentWeatherInfo.icon, | ||
| main = currentWeatherInfo.main, | ||
| lastRefreshed = currentTime, | ||
| isValid = true, | ||
| hourly = hourlyWeatherEntities, | ||
| daily = dailyWeatherEntities | ||
| ) | ||
| } | ||
|
|
||
| private fun WeatherInfoResponse.toWeatherInfoResponse(): WeatherInfoResponseEntity { | ||
| return WeatherInfoResponseEntity( | ||
| id = id, | ||
| main = main, | ||
| description = description, | ||
| icon = icon | ||
| ) | ||
| } | ||
|
|
||
| fun TemperatureResponse.toTemperatureEntity(): TemperatureEntity { | ||
| return TemperatureEntity( | ||
| min = min, | ||
| max = max | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.github.odaridavid.weatherapp.data.weather.local | ||
|
|
||
| import androidx.room.Database | ||
| import androidx.room.RoomDatabase | ||
| import androidx.room.TypeConverters | ||
| import com.github.odaridavid.weatherapp.data.weather.local.converters.Converters | ||
| import com.github.odaridavid.weatherapp.data.weather.local.dao.WeatherDao | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.WeatherEntity | ||
|
|
||
| @Database( | ||
| entities = [WeatherEntity::class], | ||
| version = 3, | ||
| exportSchema = false | ||
| ) | ||
| @TypeConverters(Converters::class) | ||
| abstract class WeatherDatabase: RoomDatabase(){ | ||
| abstract fun weatherDao():WeatherDao | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package com.github.odaridavid.weatherapp.data.weather.local.converters | ||
|
|
||
| import androidx.room.ProvidedTypeConverter | ||
| import androidx.room.TypeConverter | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.DailyWeatherEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.HourlyWeatherEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.TemperatureEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.WeatherInfoResponseEntity | ||
| import com.google.gson.Gson | ||
| import com.google.gson.reflect.TypeToken | ||
|
|
||
| @ProvidedTypeConverter | ||
| class Converters { | ||
| private val gson = Gson() | ||
|
|
||
| @TypeConverter | ||
| fun fromHourlyWeatherEntityList(hourlyList: List<HourlyWeatherEntity>): String { | ||
|
||
| return gson.toJson(hourlyList) | ||
| } | ||
|
|
||
| @TypeConverter | ||
| fun toHourlyWeatherEntityList(json: String): List<HourlyWeatherEntity> { | ||
| val type = object : TypeToken<List<HourlyWeatherEntity>>() {}.type | ||
| return gson.fromJson(json, type) | ||
| } | ||
|
|
||
| @TypeConverter | ||
| fun fromDailyWeatherEntityList(dailyList: List<DailyWeatherEntity>): String { | ||
| return gson.toJson(dailyList) | ||
| } | ||
|
|
||
| @TypeConverter | ||
| fun toDailyWeatherEntityList(json: String): List<DailyWeatherEntity> { | ||
| val type = object : TypeToken<List<DailyWeatherEntity>>() {}.type | ||
| return gson.fromJson(json, type) | ||
| } | ||
|
|
||
| @TypeConverter | ||
| fun fromWeatherInfoResponseEntityList(weatherList: List<WeatherInfoResponseEntity>): String { | ||
| return gson.toJson(weatherList) | ||
| } | ||
|
|
||
| @TypeConverter | ||
| fun toWeatherInfoResponseEntityList(json: String): List<WeatherInfoResponseEntity> { | ||
| val type = object : TypeToken<List<WeatherInfoResponseEntity>>() {}.type | ||
| return gson.fromJson(json, type) | ||
| } | ||
|
|
||
| @TypeConverter | ||
| fun fromTemperatureEntity(temperature: TemperatureEntity): String { | ||
| return gson.toJson(temperature) | ||
| } | ||
|
|
||
| @TypeConverter | ||
| fun toTemperatureEntity(json: String): TemperatureEntity { | ||
| return gson.fromJson(json, TemperatureEntity::class.java) | ||
| } | ||
| } | ||
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.
use something modern like moshi or kotlinx.serialization
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.
Okay. On it