-
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
Open
CalebKL
wants to merge
47
commits into
odaridavid:develop
Choose a base branch
from
CalebKL:offlineCache
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 28 commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
7756904
Added Dao, Weather Entity and Database
CalebKL 6b81d5b
updated gradle dependency for room and Workmanager
CalebKL 1039d32
DI for Local module and updated Manifest file to include notification…
CalebKL 58916aa
Added Notification Util to update weather info to the user after 15 Min
CalebKL 95d5e42
Updated mappers to include the new entity created
CalebKL f113abe
updated fetchWeather function to read data from cache and update afte…
CalebKL 6f50a41
updated WeatherApp to getWorkManagerConfigs and included Timber for D…
CalebKL 3d761b5
Added gson converter gradle dependency and created Converter class to…
CalebKL 248820e
Added typeconverters to DI, Database and updated WeatherEntity Class
CalebKL b47104f
Updated mappers and DefaultWeatherRepository with fetching the correc…
CalebKL 84a4bd1
Added testing dependencies
CalebKL 545579a
Updated Fakes with the corrected mapped responses
CalebKL 92499fd
Updated HomeViewModelIntegrationTest
CalebKL b6d13ce
Updated WeatherRepositoryUnitTest
CalebKL 20e7cd9
Resolved Conflicts with develop branch
CalebKL 50f9bb5
Resolved Conflicts with develop branch
CalebKL 6e7b82d
Removed Gson and updated type converters
CalebKL 67110cc
Refactored DAO to use relationships and updated entity and db
CalebKL 7f65822
updated mappers with the populated weather
CalebKL 7c5bd6d
Created usecase to sync updated weather and modified default weather …
CalebKL 1faa9b5
removed raw strings and updated strings.xml
CalebKL 078cfeb
removed timber config
CalebKL 715ca3f
Added DI for the WeatherUpdateScheduler
CalebKL d63ad19
Fixed failing tests and updated Fakes
CalebKL 738bda6
Merge branch 'develop' into offlineCache
CalebKL 64e6c37
Merge branch 'develop' into offlineCache
CalebKL 101ddb3
Adds Logger to DefaultWeatherRepository, HomeViewModelIntegrationTest…
CalebKL 8f4f983
Adds Logger toHomeViewModelIntegrationTest and WeatherRepositoryUnitTest
CalebKL 8d8a38b
Created RefreshWeatherUseCase Interface
CalebKL 2fdf3c3
Refactored Usecase to implement the interface created and updated DI
CalebKL 97f4dfb
Merge develop
CalebKL f928492
Merge develop
CalebKL bf60f85
Merge branch 'develop' into offlineCache
odaridavid 521a1b8
created CustomWorkerFactory
CalebKL 98335c6
Updated daos, database and entity
CalebKL 7d8555e
Merge remote-tracking branch 'origin/offlineCache' into offlineCache
CalebKL ae05432
updated viewmodel component with singleton component
CalebKL 710c0ad
Added latitude and longitude into the weather core model and updated …
CalebKL 09a8f59
refactored weather update scheduler
CalebKL 06314f4
deleted converters and replaced with room relations
CalebKL 8b77bb8
refactored usecase
CalebKL e283bb2
removed type converters from the local module
CalebKL 12e09e0
refactored repository to read daily and hourly lists
CalebKL e32d492
updated weather app with custom worker instead of hiltworker
CalebKL 81f4d4b
Maoppers update
CalebKL c868b82
Updated Fakes with the Populated Weather
CalebKL 15c0363
Fixed failing tests
CalebKL File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 23 additions & 1 deletion
24
app/src/main/java/com/github/odaridavid/weatherapp/WeatherApp.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,29 @@ | ||
| package com.github.odaridavid.weatherapp | ||
|
|
||
| import android.app.Application | ||
| import androidx.hilt.work.HiltWorkerFactory | ||
| import androidx.work.Configuration | ||
| import com.github.odaridavid.weatherapp.worker.WeatherUpdateScheduler | ||
| import dagger.hilt.android.HiltAndroidApp | ||
| import javax.inject.Inject | ||
|
|
||
| @HiltAndroidApp | ||
| class WeatherApp : Application() | ||
| class WeatherApp : Application(), Configuration.Provider{ | ||
| @Inject | ||
| lateinit var workerFactory: HiltWorkerFactory | ||
|
|
||
| @Inject | ||
| lateinit var weatherUpdateScheduler: WeatherUpdateScheduler | ||
|
|
||
| override fun onCreate() { | ||
| super.onCreate() | ||
| schedulePeriodicWeatherUpdates() | ||
| } | ||
|
|
||
| override fun getWorkManagerConfiguration(): Configuration = | ||
| Configuration.Builder().setWorkerFactory(workerFactory).build() | ||
|
|
||
| private fun schedulePeriodicWeatherUpdates() { | ||
| weatherUpdateScheduler.schedulePeriodicWeatherUpdates() | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,10 +8,17 @@ 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.PopulatedWeather | ||
| 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 | ||
|
|
||
|
|
||
| fun WeatherResponse.toCoreModel(unit: String): Weather = Weather( | ||
| current = current.toCoreModel(unit = unit), | ||
| daily = daily.map { it.toCoreModel(unit = unit) }, | ||
|
|
@@ -52,6 +59,57 @@ fun TemperatureResponse.toCoreModel(unit: String): Temperature = | |
| min = formatTemperatureValue(min, unit), | ||
| max = formatTemperatureValue(max, unit) | ||
| ) | ||
| fun PopulatedWeather.toCoreEntity(unit: String): Weather = | ||
| Weather( | ||
| current = toCurrentWeather(unit = unit), | ||
| hourly = hourly.map{it.asCoreModel(unit = unit)}, | ||
| daily = daily.map { | ||
| it.asCoreModel(unit = unit) } | ||
| ) | ||
|
|
||
| private fun PopulatedWeather.toCurrentWeather(unit: String): CurrentWeather = | ||
| CurrentWeather( | ||
| temperature = formatTemperatureValue(current.temp, unit), | ||
| feelsLike = formatTemperatureValue(current.feels_like, unit), | ||
| weather = listOf( | ||
| WeatherInfo( | ||
| id = current.id, | ||
| main = current.main, | ||
| description = current.description, | ||
| icon = current.icon | ||
| ) | ||
| ) | ||
| ) | ||
| fun DailyWeatherEntity.asCoreModel(unit: String): DailyWeather = | ||
| DailyWeather( | ||
| forecastedTime = getDate(dt,"EEEE dd/M"), | ||
| temperature = temperature.asCoreModel(unit = unit), | ||
| weather = weather.map { it.asCoreModel() } | ||
| ) | ||
|
|
||
| fun HourlyWeatherEntity.asCoreModel(unit: String): HourlyWeather = | ||
| HourlyWeather( | ||
| forecastedTime = getDate(dt,"HH:SS"), | ||
| temperature = formatTemperatureValue(temperature, unit), | ||
| weather = weather.map { it.asCoreModel() } | ||
| ) | ||
|
|
||
| fun WeatherInfoResponseEntity.asCoreModel(): WeatherInfo = | ||
| WeatherInfo( | ||
| id = id, | ||
| main = main, | ||
| description = description, | ||
| icon = "${BuildConfig.OPEN_WEATHER_ICONS_URL}[email protected]" | ||
| ) | ||
| fun TemperatureEntity.asCoreModel(unit: String): Temperature = | ||
| Temperature( | ||
| min = formatTemperatureValue(min, unit), | ||
| max = formatTemperatureValue(max, unit) | ||
| ) | ||
|
|
||
| fun WeatherInfoResponseEntity.toWeatherInfo(): WeatherInfo { | ||
| return WeatherInfo(id, main, description, icon) | ||
| } | ||
|
|
||
| private fun formatTemperatureValue(temperature: Float, unit: String): String = | ||
| "${temperature.roundToInt()}${getUnitSymbols(unit = unit)}" | ||
|
|
@@ -68,3 +126,59 @@ private fun getDate(utcInMillis: Long, formatPattern: String): String { | |
| val dateFormat = Date(utcInMillis * 1000) | ||
| return sdf.format(dateFormat) | ||
| } | ||
|
|
||
| fun WeatherResponse.toHourlyEntity():List<HourlyWeatherEntity> { | ||
| val hourlyWeatherEntities = hourly.map { hourlyResponse -> | ||
| HourlyWeatherEntity( | ||
| dt = hourlyResponse.forecastedTime, | ||
| temperature = hourlyResponse.temperature, | ||
| weather = hourlyResponse.weather.map { it.toWeatherInfoResponse() } | ||
| ) | ||
| } | ||
| return hourlyWeatherEntities | ||
| } | ||
| fun WeatherResponse.toDailyEntity():List<DailyWeatherEntity> { | ||
| val dailyWeatherEntities = daily.map { dailyResponse -> | ||
| DailyWeatherEntity( | ||
| dt = dailyResponse.forecastedTime, | ||
| temperature = dailyResponse.temperature.toTemperatureEntity(), | ||
| weather = dailyResponse.weather.map { it.toWeatherInfoResponse() } | ||
| ) | ||
| } | ||
| return dailyWeatherEntities | ||
| } | ||
|
|
||
| fun WeatherResponse.toCurrentWeatherEntity(): WeatherEntity { | ||
| val currentTime = System.currentTimeMillis() | ||
| val currentWeatherInfo = current.weather.first() | ||
|
|
||
| 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, | ||
| ) | ||
| } | ||
|
|
||
| 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 | ||
| ) | ||
| } | ||
45 changes: 45 additions & 0 deletions
45
app/src/main/java/com/github/odaridavid/weatherapp/data/weather/RefreshWeatherUseCase.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package com.github.odaridavid.weatherapp.data.weather | ||
|
|
||
| import android.content.Context | ||
| import com.github.odaridavid.weatherapp.R | ||
| import com.github.odaridavid.weatherapp.core.api.WeatherRepository | ||
| import com.github.odaridavid.weatherapp.core.model.DefaultLocation | ||
| import com.github.odaridavid.weatherapp.core.model.Weather | ||
| import com.github.odaridavid.weatherapp.util.NotificationUtil | ||
| import kotlinx.coroutines.flow.Flow | ||
| import kotlinx.coroutines.flow.flow | ||
| import javax.inject.Inject | ||
|
|
||
| class RefreshWeatherUseCase @Inject constructor( | ||
odaridavid marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| private val weatherRepository: WeatherRepository, | ||
| private val notificationUtil: NotificationUtil, | ||
| private val context: Context | ||
| ) { | ||
| operator fun invoke( | ||
| defaultLocation: DefaultLocation, | ||
| language: String, | ||
| units: String | ||
| ): Flow<ApiResult<Weather>> = flow{ | ||
| weatherRepository.fetchWeatherData( | ||
| defaultLocation = defaultLocation, | ||
| language = language, | ||
| units =units | ||
| ).collect{ result-> | ||
| when (result) { | ||
| is ApiResult.Success -> { | ||
| notificationUtil.makeNotification(context.getString(R.string.weather_updates)) | ||
| } | ||
| is ApiResult.Error -> { | ||
| R.string.error_generic | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
23 changes: 23 additions & 0 deletions
23
app/src/main/java/com/github/odaridavid/weatherapp/data/weather/local/WeatherDatabase.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| 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.DailyWeatherEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.HourlyWeatherEntity | ||
| import com.github.odaridavid.weatherapp.data.weather.local.entity.WeatherEntity | ||
|
|
||
| @Database( | ||
| entities = [ | ||
| WeatherEntity::class, | ||
| HourlyWeatherEntity::class, | ||
| DailyWeatherEntity::class], | ||
| version = 5, | ||
| exportSchema = false | ||
| ) | ||
| @TypeConverters(Converters::class) | ||
| abstract class WeatherDatabase: RoomDatabase(){ | ||
| abstract fun weatherDao():WeatherDao | ||
| } |
19 changes: 19 additions & 0 deletions
19
...rc/main/java/com/github/odaridavid/weatherapp/data/weather/local/converters/Converters.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| 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.WeatherInfoResponseEntity | ||
| import kotlinx.serialization.decodeFromString | ||
| import kotlinx.serialization.encodeToString | ||
| import kotlinx.serialization.json.Json | ||
|
|
||
| @ProvidedTypeConverter | ||
| class Converters { | ||
|
|
||
| @TypeConverter | ||
| fun fromWeatherInfo(value: List<WeatherInfoResponseEntity>?): String = Json.encodeToString(value) | ||
|
|
||
| @TypeConverter | ||
| fun toWeatherInfo(value: String?) = value?.let { Json.decodeFromString<List<WeatherInfoResponseEntity>>(it) } | ||
|
|
||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.