Skip to content

Part2.3

Arnaud Giuliani edited this page Sep 27, 2018 · 25 revisions

Steps



2.3 - Update the weather repository and run

We are now ready! We can put all the Room components together to write an room version of our DailyForecastRepository


TODO 🎯 - Create the DailyForecastRepositoryRoomImpl class

Let's create a new version of the DailyForecastRepositoryImpl as a Room version: DailyForecastRepositoryRoomImpl in package domain/repository. Copy the DailyForecastRepositoryImpl class and replace with the code below, which uses WeatherDAO instead of local memory cache.

  • Write constructor as follow:
class DailyForecastRepositoryRoomImpl(
    private val weatherDatasource: WeatherDataSource,
    private val weatherDAO: WeatherDAO
) : DailyForecastRepository {
  • Remove lastLocationFromCache() function and weatherCache property

Now, we need to rework functions as follow:

  • Rewrite getWeatherDetail() function to use directly the DAO:
// Get weather from its id
override fun getWeatherDetail(id: String): Single<DailyForecast> =
    weatherDAO.findWeatherById(id).map { DailyForecast.from(it) }
  • Rewrite getWeather() as follow: use 2 functions (getNewWeather() and getWeatherFromLatest()) and requests last weather or a new one:
// Get weather from latest or default one if the location is null
// else get new weather
override fun getWeather(
    location: String?
): Single<List<DailyForecast>> {
    return if (location == null) {
        weatherDAO.findLatestWeather().flatMap { latest: List<WeatherEntity> ->
            if (latest.isEmpty()) getNewWeather(DEFAULT_LOCATION) else getWeatherFromLatest(latest.first())
        }
    } else {
        getNewWeather(location)
    }
}
  • Add the following getNewWeather() function to request a new weather for location:
// Get new weather and save it
private fun getNewWeather(location: String): Single<List<DailyForecast>> {
    val now = Date()
    return weatherDatasource.geocode(location)
        .map { it.getLocation() ?: throw IllegalStateException("No Location date") }
        .flatMap { weatherDatasource.weather(it.lat, it.lng, DEFAULT_LANG) }
        .map { it.getDailyForecasts(location) }
        .doOnSuccess { list ->
            weatherDAO.saveAll(list.map { item -> WeatherEntity.from(item, now) })
        }
}
  • Add the getWeatherFromLatest() function which requests latest weather data:
// Find latest weather
private fun getWeatherFromLatest(latest: WeatherEntity): Single<List<DailyForecast>> {
    return weatherDAO.findAllBy(latest.location, latest.date)
        .map { list -> list.map { DailyForecast.from(it) } }
}

Now, the DailyForecastRepositoryRoomImpl should compile! βœ…


TODO 🎯 - Update Koin configuration:

In room_datasource_module.kt, add and override the DailyForecastRepository definition for the new DailyForecastRepositoryRoomImpl constructor (add an additional get() to fill dependency for constructor, else you'll get a compilation error):

Add the following definition:

// Weather Room Data Repository
single<DailyForecastRepository>(override = true) { DailyForecastRepositoryRoomImpl(get(),get()) }

Note πŸ“–: We keep both implementation of DailyForecastRepository by using moduel configuration change. It also allow us to not break our tests.


TODO 🎯 - Run last tests

  • Uncomment WeatherRepositoryTest from Android test
  • Comment datasource/WeatherRepositoryTest from unit tests
  • Run all tests from Android test WeatherRepositoryTest
  • Run the weather app on your device!

Make sure all tests are passing (Unit & Android)!


Congrats, You're done πŸ‘ 🍾

The weather app now stores your last location. Kill the app and restart it. You should have your last location instead of the default "Paris" location.

Clone this wiki locally