Saving a forecast
The
saveForecast
function just clears the data from the database so that we save fresh data, converts
the domain forecast model to database model, and inserts each daily forecast and the city forecast.
The structure is similar to the previous one: it returns the value from the
use
function from the
database helper. In this case we don’t need a result, so it’ll return
Unit
.
1
fun saveForecast(forecast: ForecastList) = forecastDbHelper.use {
2
...
3
}
First, we clear both tables. Anko doesn’t provide any beautiful way to do it, but it doesn’t mean we
can’t. So we are creating an extension function for
SQLiteDatabase
that will execute the proper SQL
query for us:
1
fun SQLiteDatabase.clear(tableName: String) {
2
execSQL("delete from $tableName")
3
}
The function is applied to both tables:
19 Saving and requesting data from database
87
1
clear(CityForecastTable.NAME)
2
clear(DayForecastTable.NAME)
Now it’s time to convert the data, and use the result to execute the
insert
queries. At this point you
probably know I’m a fan of the
with
function:
1
with(dataMapper.convertFromDomain(forecast)) {
2
...
3
}
The conversion from the domain model is straightforward too:
1
fun convertFromDomain(forecast: ForecastList) = with(forecast) {
2
val daily = dailyForecast.map { convertDayFromDomain(id, it) }
3
CityForecast(id, city, country, daily)
4
}
5
6
private fun convertDayFromDomain(cityId: Long, forecast: Forecast) =
7
with(forecast) {
8
DayForecast(date, description, high, low, iconUrl, cityId)
9
}
Inside the block, we can use
dailyForecast
and
map
without the need of referring to a variable, just
like if we were inside the class. We are using another Anko function for the insertion, which asks
for a table name and a
vararg
of
Pair
. The function will convert the
vararg
to the
ContentValues
object the Android SDK needs. So our task consists of transforming the
map
into a
vararg
array. We are creating another extension function for
MutableMap
to do that:
1
fun MutableMap.toVarargArray():
2
Array> =
map({ Pair(it.key, it.value!!) }).toTypedArray()
It works over a
MutableMap
with nullable values (this was a condition from the map delegate), and
converts it to an
Array
with non-nullable values (
select
function requisite) of pairs. Don’t worry if
you don’t understand this function completely, I will be covering nullity really soon.
So, with this new function we can do:
1
insert(CityForecastTable.NAME, *map.toVarargArray())
It inserts a new row in the
CityForecast
table. The ‘
*
’ used before the result of
toVarargArray
indicates that the array will be decomposed to a
vararg
parameter. This is done automatically in
Java, but we need to make it explicit in Kotlin.
And the same for each daily forecast:
19 Saving and requesting data from database
88
1
dailyForecast.forEach { insert(DayForecastTable.NAME, *it.map.toVarargArray()) }
So, with the use of maps, we’ve been able to convert classes to database registers and viceversa in a
very simple way. Once we have these extension functions ready, we can use them for other projects,
so it’s a really well paid effort.
The complete code of this function:
1
fun saveForecast(forecast: ForecastList) = forecastDbHelper.use {
2
3
clear(CityForecastTable.NAME)
4
clear(DayForecastTable.NAME)
5
6
with(dataMapper.convertFromDomain(forecast)) {
7
insert(CityForecastTable.NAME, *map.toVarargArray())
8
dailyForecast forEach {
9
insert(DayForecastTable.NAME, *it.map.toVarargArray())
10
}
11
}
12
}
A lot of new code was involved in this chapter, so you can take a look at the repository to review it.
Do'stlaringiz bilan baham: |