fix crashes due to race conditions when changing data source

This commit is contained in:
johan12345
2022-09-11 18:07:08 +02:00
parent 3c30481821
commit 89b2175d89
3 changed files with 31 additions and 32 deletions

View File

@@ -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<ChargepointApi<ReferenceData>>().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<Resource<List<ChargepointListItem>>> {
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<Resource<List<ChargepointListItem>>> {
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<Resource<ChargeLocation>> {
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
}
}
}
}

View File

@@ -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<Map<Long, ChargeCard>> by lazy {
MediatorLiveData<Map<Long, ChargeCard>>().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<Int> by lazy {
MediatorLiveData<Int>().apply {

View File

@@ -109,7 +109,8 @@ fun <T> throttleLatest(
public suspend fun <T> LiveData<T>.await(): T {
return suspendCancellableCoroutine { continuation ->
val observer = object : Observer<T> {
override fun onChanged(value: T) {
override fun onChanged(value: T?) {
if (value == null) return
removeObserver(this)
continuation.resume(value, null)
}