Build a Room database for favorites

This commit is contained in:
Johan von Forstner
2020-04-17 20:16:55 +02:00
parent 6e93e602b1
commit 20a1dea2cd
7 changed files with 143 additions and 22 deletions

View File

@@ -3,6 +3,9 @@ package net.vonforst.evmap.api.goingelectric
import android.content.Context
import android.os.Parcelable
import androidx.core.text.HtmlCompat
import androidx.room.Embedded
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import kotlinx.android.parcel.Parcelize
@@ -21,11 +24,12 @@ data class ChargepointList(
sealed class ChargepointListItem
@JsonClass(generateAdapter = true)
@Entity
data class ChargeLocation(
@Json(name = "ge_id") val id: Long,
@Json(name = "ge_id") @PrimaryKey val id: Long,
val name: String,
val coordinates: Coordinate,
val address: Address,
@Embedded val coordinates: Coordinate,
@Embedded val address: Address,
val chargepoints: List<Chargepoint>,
@JsonObjectOrFalse val network: String?,
val url: String,
@@ -38,8 +42,8 @@ data class ChargeLocation(
@JsonObjectOrFalse @Json(name = "location_description") val locationDescription: String?,
val photos: List<ChargerPhoto>?,
//val chargecards: Boolean?
val openinghours: OpeningHours?,
val cost: Cost?
@Embedded val openinghours: OpeningHours?,
@Embedded val cost: Cost?
) : ChargepointListItem() {
val maxPower: Double
get() {
@@ -75,7 +79,7 @@ data class Cost(
data class OpeningHours(
@Json(name = "24/7") val twentyfourSeven: Boolean,
@JsonObjectOrFalse val description: String?,
val days: OpeningHoursDays?
@Embedded val days: OpeningHoursDays?
) {
fun getStatusText(ctx: Context): CharSequence {
if (twentyfourSeven) {
@@ -114,14 +118,14 @@ data class OpeningHours(
@JsonClass(generateAdapter = true)
data class OpeningHoursDays(
val monday: Hours,
val tuesday: Hours,
val wednesday: Hours,
val thursday: Hours,
val friday: Hours,
val saturday: Hours,
val sunday: Hours,
val holiday: Hours
@Embedded(prefix = "mo") val monday: Hours,
@Embedded(prefix = "tu") val tuesday: Hours,
@Embedded(prefix = "we") val wednesday: Hours,
@Embedded(prefix = "th") val thursday: Hours,
@Embedded(prefix = "fr") val friday: Hours,
@Embedded(prefix = "sa") val saturday: Hours,
@Embedded(prefix = "su") val sunday: Hours,
@Embedded(prefix = "ho") val holiday: Hours
) {
fun getHoursForDate(date: LocalDate): Hours {
// TODO: check for holidays

View File

@@ -58,7 +58,12 @@ const val REQUEST_AUTOCOMPLETE = 2
class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallback {
private lateinit var binding: FragmentMapBinding
private val vm: MapViewModel by viewModels(factoryProducer = {
viewModelFactory { MapViewModel(getString(R.string.goingelectric_key)) }
viewModelFactory {
MapViewModel(
requireActivity().application,
getString(R.string.goingelectric_key)
)
}
})
private val galleryVm: GalleryViewModel by activityViewModels()
private var map: GoogleMap? = null

View File

@@ -0,0 +1,17 @@
package net.vonforst.evmap.storage
import androidx.lifecycle.LiveData
import androidx.room.*
import net.vonforst.evmap.api.goingelectric.ChargeLocation
@Dao
interface ChargeLocationsDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg locations: ChargeLocation)
@Delete
fun delete(vararg locations: ChargeLocation)
@Query("SELECT * FROM chargelocation")
fun getAllChargeLocations(): LiveData<List<ChargeLocation>>
}

View File

@@ -0,0 +1,26 @@
package net.vonforst.evmap.storage
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import net.vonforst.evmap.api.goingelectric.ChargeLocation
@Database(entities = [ChargeLocation::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun chargeLocationsDao(): ChargeLocationsDao
companion object {
private lateinit var context: Context
private val database: AppDatabase by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
Room.databaseBuilder(context, AppDatabase::class.java, "evmap.db").build()
}
fun getInstance(context: Context): AppDatabase {
this.context = context.applicationContext
return database
}
}
}

View File

@@ -0,0 +1,52 @@
package net.vonforst.evmap.storage
import androidx.room.TypeConverter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import net.vonforst.evmap.api.goingelectric.Chargepoint
import net.vonforst.evmap.api.goingelectric.ChargerPhoto
import java.time.LocalTime
class Converters {
val moshi = Moshi.Builder().build()
private val chargepointListAdapter by lazy {
val type = Types.newParameterizedType(List::class.java, Chargepoint::class.java)
moshi.adapter<List<Chargepoint>>(type)
}
private val chargerPhotoListAdapter by lazy {
val type = Types.newParameterizedType(List::class.java, ChargerPhoto::class.java)
moshi.adapter<List<ChargerPhoto>>(type)
}
@TypeConverter
fun fromChargepointList(value: List<Chargepoint>): String {
return chargepointListAdapter.toJson(value)
}
@TypeConverter
fun toChargepointList(value: String): List<Chargepoint> {
return chargepointListAdapter.fromJson(value)!!
}
@TypeConverter
fun fromChargerPhotoList(value: List<ChargerPhoto>): String {
return chargerPhotoListAdapter.toJson(value)
}
@TypeConverter
fun toChargerPhotoList(value: String): List<ChargerPhoto> {
return chargerPhotoListAdapter.fromJson(value)!!
}
@TypeConverter
fun fromLocalTime(value: LocalTime?): String? {
return value?.toString()
}
@TypeConverter
fun toLocalTime(value: String?): LocalTime? {
return value.let {
LocalTime.parse(it)
}
}
}

View File

@@ -1,9 +1,7 @@
package net.vonforst.evmap.viewmodel
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import android.app.Application
import androidx.lifecycle.*
import com.google.android.gms.maps.model.LatLngBounds
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -15,6 +13,7 @@ import net.vonforst.evmap.api.goingelectric.ChargeLocation
import net.vonforst.evmap.api.goingelectric.ChargepointList
import net.vonforst.evmap.api.goingelectric.ChargepointListItem
import net.vonforst.evmap.api.goingelectric.GoingElectricApi
import net.vonforst.evmap.storage.AppDatabase
import retrofit2.Call
import retrofit2.Callback
import retrofit2.HttpException
@@ -23,9 +22,9 @@ import java.io.IOException
data class MapPosition(val bounds: LatLngBounds, val zoom: Float)
class MapViewModel(geApiKey: String) : ViewModel() {
private var api: GoingElectricApi =
GoingElectricApi.create(geApiKey)
class MapViewModel(application: Application, geApiKey: String) : AndroidViewModel(application) {
private var api = GoingElectricApi.create(geApiKey)
private var db = AppDatabase.getInstance(application)
val bottomSheetState: MutableLiveData<Int> by lazy {
MutableLiveData<Int>()
@@ -87,6 +86,18 @@ class MapViewModel(geApiKey: String) : ViewModel() {
MutableLiveData<Boolean>()
}
val favorites: LiveData<List<ChargeLocation>> by lazy {
db.chargeLocationsDao().getAllChargeLocations()
}
fun insertFavorite(charger: ChargeLocation) {
db.chargeLocationsDao().insert(charger)
}
fun deleteFavorite(charger: ChargeLocation) {
db.chargeLocationsDao().delete(charger)
}
private fun loadChargepoints(mapPosition: MapPosition) {
chargepoints.value = Resource.loading(chargepoints.value?.data)
val bounds = mapPosition.bounds