From 89b2175d89d73ea83e4c0941358a325accd6d4b2 Mon Sep 17 00:00:00 2001 From: johan12345 Date: Sun, 11 Sep 2022 18:07:08 +0200 Subject: [PATCH] fix crashes due to race conditions when changing data source --- .../evmap/storage/ChargeLocationsDao.kt | 44 ++++++++++++------- .../vonforst/evmap/viewmodel/MapViewModel.kt | 16 +------ .../net/vonforst/evmap/viewmodel/Utils.kt | 3 +- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/net/vonforst/evmap/storage/ChargeLocationsDao.kt b/app/src/main/java/net/vonforst/evmap/storage/ChargeLocationsDao.kt index 08b03753..1a347de0 100644 --- a/app/src/main/java/net/vonforst/evmap/storage/ChargeLocationsDao.kt +++ b/app/src/main/java/net/vonforst/evmap/storage/ChargeLocationsDao.kt @@ -10,6 +10,7 @@ import com.car2go.maps.model.LatLngBounds import kotlinx.coroutines.CoroutineScope import net.vonforst.evmap.api.ChargepointApi import net.vonforst.evmap.api.StringProvider +import net.vonforst.evmap.api.goingelectric.GEReferenceData import net.vonforst.evmap.api.goingelectric.GoingElectricApiWrapper import net.vonforst.evmap.api.openchargemap.OpenChargeMapApiWrapper import net.vonforst.evmap.model.ChargeLocation @@ -38,29 +39,31 @@ class ChargeLocationsRepository( ) { val api = MutableLiveData>().apply { value = api } - val referenceData = this.api.switchMap { - when (it) { + private val apiAndReferenceData = this.api.switchMap { api -> + when (api) { is GoingElectricApiWrapper -> { GEReferenceDataRepository( - it, + api, scope, db.geReferenceDataDao(), prefs - ).getReferenceData() + ).getReferenceData().map { api to it } } is OpenChargeMapApiWrapper -> { OCMReferenceDataRepository( - it, + api, scope, db.ocmReferenceDataDao(), prefs - ).getReferenceData() + ).getReferenceData().map { api to it } } else -> { throw RuntimeException("no reference data implemented") } } } + val referenceData = apiAndReferenceData.map { it.second } + private val chargeLocationsDao = db.chargeLocationsDao() fun getChargepoints( @@ -68,9 +71,8 @@ class ChargeLocationsRepository( zoom: Float, filters: FilterValues? ): LiveData>> { - val api = api.value!! return liveData { - val refData = referenceData.await() + val (api, refData) = apiAndReferenceData.await() val result = api.getChargepoints(refData, bounds, zoom, filters) emit(result) @@ -83,11 +85,9 @@ class ChargeLocationsRepository( zoom: Float, filters: FilterValues? ): LiveData>> { - val api = api.value!! return liveData { - val refData = referenceData.await() - val result = - api.getChargepointsRadius(refData, location, radius, zoom, filters) + val (api, refData) = apiAndReferenceData.await() + val result = api.getChargepointsRadius(refData, location, radius, zoom, filters) emit(result) } @@ -97,13 +97,25 @@ class ChargeLocationsRepository( id: Long ): LiveData> { return liveData { - val refData = referenceData.await() - val result = api.value!!.getChargepointDetail(refData, id) + val (api, refData) = apiAndReferenceData.await() + val result = api.getChargepointDetail(refData, id) emit(result) } } - fun getFilters(sp: StringProvider) = referenceData.map { data -> - api.value!!.getFilters(data, sp) + fun getFilters(sp: StringProvider) = apiAndReferenceData.map { (api, refData) -> + api.getFilters(refData, sp) + } + + val chargeCardMap by lazy { + apiAndReferenceData.map { (_, refData) -> + if (refData is GEReferenceData) { + refData.chargecards.associate { + it.id to it.convert() + } + } else { + null + } + } } } \ No newline at end of file diff --git a/app/src/main/java/net/vonforst/evmap/viewmodel/MapViewModel.kt b/app/src/main/java/net/vonforst/evmap/viewmodel/MapViewModel.kt index 5a571f6f..a4e13b8f 100644 --- a/app/src/main/java/net/vonforst/evmap/viewmodel/MapViewModel.kt +++ b/app/src/main/java/net/vonforst/evmap/viewmodel/MapViewModel.kt @@ -14,7 +14,6 @@ import net.vonforst.evmap.api.availability.ChargeLocationStatus import net.vonforst.evmap.api.availability.getAvailability import net.vonforst.evmap.api.createApi import net.vonforst.evmap.api.goingelectric.GEChargepoint -import net.vonforst.evmap.api.goingelectric.GEReferenceData import net.vonforst.evmap.api.openchargemap.OCMConnection import net.vonforst.evmap.api.openchargemap.OCMReferenceData import net.vonforst.evmap.api.stringProvider @@ -83,20 +82,7 @@ class MapViewModel(application: Application, private val state: SavedStateHandle db.filterProfileDao().getProfiles(prefs.dataSource) } - val chargeCardMap: LiveData> by lazy { - MediatorLiveData>().apply { - value = null - addSource(repo.referenceData) { data -> - value = if (data is GEReferenceData) { - data.chargecards.map { - it.id to it.convert() - }.toMap() - } else { - null - } - } - } - } + val chargeCardMap = repo.chargeCardMap val filtersCount: LiveData by lazy { MediatorLiveData().apply { diff --git a/app/src/main/java/net/vonforst/evmap/viewmodel/Utils.kt b/app/src/main/java/net/vonforst/evmap/viewmodel/Utils.kt index ced76222..a5e8bc5b 100644 --- a/app/src/main/java/net/vonforst/evmap/viewmodel/Utils.kt +++ b/app/src/main/java/net/vonforst/evmap/viewmodel/Utils.kt @@ -109,7 +109,8 @@ fun throttleLatest( public suspend fun LiveData.await(): T { return suspendCancellableCoroutine { continuation -> val observer = object : Observer { - override fun onChanged(value: T) { + override fun onChanged(value: T?) { + if (value == null) return removeObserver(this) continuation.resume(value, null) }