Refactor weather widget

This commit is contained in:
MM20
2021-12-19 21:58:19 +01:00
parent 2ee50459a9
commit b9054f04cd
8 changed files with 256 additions and 166 deletions
@@ -0,0 +1,8 @@
package de.mm20.launcher2.weather
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
val weatherModule = module {
single { WeatherRepository(androidContext(), get()) }
}
@@ -2,31 +2,35 @@ package de.mm20.launcher2.weather
import android.content.Context
import android.util.Log
import androidx.lifecycle.MediatorLiveData
import androidx.work.*
import de.mm20.launcher2.database.AppDatabase
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import java.util.*
import java.util.concurrent.TimeUnit
class WeatherRepository(
val context: Context
val context: Context,
val database: AppDatabase,
) {
val forecasts = MediatorLiveData<List<DailyForecast>>()
init {
forecasts.addSource(AppDatabase.getInstance(context).weatherDao().getForecasts()) { entities ->
forecasts.value = sortDailyForecasts(entities.map { Forecast(it) })
val forecasts = database.weatherDao().getForecasts()
.map { it.map { Forecast(it) } }
.map {
groupForecastsPerDay(it)
}
val weatherRequest = PeriodicWorkRequest.Builder(WeatherUpdateWorker::class.java, 60, TimeUnit.MINUTES)
init {
val weatherRequest =
PeriodicWorkRequest.Builder(WeatherUpdateWorker::class.java, 60, TimeUnit.MINUTES)
.build()
WorkManager.getInstance().enqueueUniquePeriodicWork("weather",
ExistingPeriodicWorkPolicy.KEEP, weatherRequest)
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"weather",
ExistingPeriodicWorkPolicy.KEEP, weatherRequest
)
}
private fun sortDailyForecasts(forecasts: List<Forecast>): List<DailyForecast> {
private fun groupForecastsPerDay(forecasts: List<Forecast>): List<DailyForecast> {
val dailyForecasts = mutableListOf<DailyForecast>()
val calendar = Calendar.getInstance()
var currentDay = 0
@@ -35,12 +39,16 @@ class WeatherRepository(
calendar.timeInMillis = fc.timestamp
if (currentDay != calendar.get(Calendar.DAY_OF_YEAR)) {
if (currentDayForecasts.isNotEmpty()) {
dailyForecasts.add(DailyForecast(
dailyForecasts.add(
DailyForecast(
timestamp = currentDayForecasts.first().timestamp,
minTemp = currentDayForecasts.minByOrNull { it.temperature }?.temperature ?: 0.0,
maxTemp = currentDayForecasts.maxByOrNull { it.temperature }?.temperature ?: 0.0,
minTemp = currentDayForecasts.minByOrNull { it.temperature }?.temperature
?: 0.0,
maxTemp = currentDayForecasts.maxByOrNull { it.temperature }?.temperature
?: 0.0,
hourlyForecasts = currentDayForecasts
))
)
)
currentDayForecasts = mutableListOf()
}
currentDay = calendar.get(Calendar.DAY_OF_YEAR)
@@ -48,12 +56,16 @@ class WeatherRepository(
currentDayForecasts.add(fc)
}
if (currentDayForecasts.isNotEmpty()) {
dailyForecasts.add(DailyForecast(
dailyForecasts.add(
DailyForecast(
timestamp = currentDayForecasts.first().timestamp,
minTemp = currentDayForecasts.minByOrNull { it.temperature }?.temperature ?: 0.0,
maxTemp = currentDayForecasts.maxByOrNull { it.temperature }?.temperature ?: 0.0,
minTemp = currentDayForecasts.minByOrNull { it.temperature }?.temperature
?: 0.0,
maxTemp = currentDayForecasts.maxByOrNull { it.temperature }?.temperature
?: 0.0,
hourlyForecasts = currentDayForecasts
))
)
)
}
return dailyForecasts
}
@@ -63,8 +75,8 @@ class WeatherRepository(
val provider = WeatherProvider.getInstance(context) ?: return
if (provider.isUpdateRequired()) {
val weatherRequest = OneTimeWorkRequest.Builder(WeatherUpdateWorker::class.java)
.addTag("weather")
.build()
.addTag("weather")
.build()
WorkManager.getInstance(context).enqueue(weatherRequest)
} else {
Log.d("MM20", "No weather update required")
@@ -72,7 +84,8 @@ class WeatherRepository(
}
}
class WeatherUpdateWorker(val context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
class WeatherUpdateWorker(val context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val provider = WeatherProvider.getInstance(context) ?: return Result.failure()
if (!provider.isAvailable()) return Result.failure()
@@ -83,7 +96,8 @@ class WeatherUpdateWorker(val context: Context, params: WorkerParameters) : Coro
Result.retry()
} else {
Log.d("MM20", "Weather update succeeded")
AppDatabase.getInstance(applicationContext).weatherDao().replaceAll(weatherData.map { it.toDatabaseEntity() })
AppDatabase.getInstance(applicationContext).weatherDao()
.replaceAll(weatherData.map { it.toDatabaseEntity() })
Result.success()
}
}
@@ -4,19 +4,17 @@ import android.app.Application
import android.content.Context
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
class WeatherViewModel(application: Application) : AndroidViewModel(application) {
class WeatherViewModel(application: Application) : AndroidViewModel(application), KoinComponent {
private val repository = WeatherRepository(application)
private val repository : WeatherRepository by inject()
init {
requestUpdate(application)
}
val forecasts: LiveData<List<DailyForecast>> by lazy {
repository.forecasts
}
fun requestUpdate(context: Context) {
repository.requestUpdate(context)
}