Added coroutine exception handler to EntriesViewModel.kt

This commit is contained in:
Arty Bishop committed 2021-10-27 21:47:02 +01:00
1 parent b6d019ace7
commit 6fa63fdcff
6 files changed
+45 -42

No files matched your search

@@ -17,8 +17,9 @@
*/
package com.rtbishop.look4sat.framework.model
sealed class Result<out T : Any> {
data class Success<out T : Any>(val data: T) : Result<T>()
data class Error(val exception: Throwable) : Result<Nothing>()
object InProgress : Result<Nothing>()
sealed class DataState<out T> {
data class Success<out T>(val data: T) : DataState<T>()
data class Error(val error: Throwable) : DataState<Nothing>()
object Empty : DataState<Nothing>()
object Loading : DataState<Nothing>()
}
@@ -29,7 +29,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.data.SatItem
import com.rtbishop.look4sat.databinding.FragmentEntriesBinding
import com.rtbishop.look4sat.framework.model.Result
import com.rtbishop.look4sat.framework.model.DataState
import com.rtbishop.look4sat.utility.RecyclerDivider
import com.rtbishop.look4sat.utility.getNavResult
import com.rtbishop.look4sat.utility.navigateSafe
@@ -79,21 +79,21 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
}
private fun handleSatData(
result: Result<List<SatItem>>,
dataState: DataState<List<SatItem>>,
binding: FragmentEntriesBinding,
entriesAdapter: EntriesAdapter
) {
when (result) {
is Result.Success -> {
entriesAdapter.submitList(result.data)
when (dataState) {
is DataState.Success -> {
entriesAdapter.submitList(dataState.data)
binding.entriesProgress.visibility = View.INVISIBLE
binding.entriesRecycler.visibility = View.VISIBLE
}
is Result.InProgress -> {
is DataState.Loading -> {
binding.entriesProgress.visibility = View.VISIBLE
binding.entriesRecycler.visibility = View.INVISIBLE
}
is Result.Error -> {
is DataState.Error -> {
binding.entriesProgress.visibility = View.INVISIBLE
binding.entriesRecycler.visibility = View.VISIBLE
requireView().showSnack(getString(R.string.entries_update_error))
@@ -24,10 +24,12 @@ import androidx.lifecycle.*
import com.rtbishop.look4sat.data.Preferences
import com.rtbishop.look4sat.data.SatelliteRepo
import com.rtbishop.look4sat.data.SatItem
import com.rtbishop.look4sat.framework.model.Result
import com.rtbishop.look4sat.framework.model.DataState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.*
import javax.inject.Inject
@@ -38,46 +40,46 @@ class EntriesViewModel @Inject constructor(
private val satelliteRepo: SatelliteRepo,
) : ViewModel(), EntriesAdapter.EntriesClickListener, SearchView.OnQueryTextListener {
private val coroutineHandler = CoroutineExceptionHandler { _, throwable ->
Timber.d(throwable)
_satData.value = DataState.Error(throwable)
}
private val transModes = MutableLiveData(satelliteRepo.loadSelectedModes())
private val currentQuery = MutableLiveData(String())
private val itemsWithModes = transModes.switchMap { modes ->
liveData { satelliteRepo.getSatItems().collect { emit(filterByModes(it, modes)) } }
}
private val itemsWithQuery = currentQuery.switchMap { query ->
itemsWithModes.map { items -> Result.Success(filterByQuery(items, query)) }
itemsWithModes.map { items -> DataState.Success(filterByQuery(items, query)) }
}
private val _satData = MediatorLiveData<Result<List<SatItem>>>().apply {
private val _satData = MediatorLiveData<DataState<List<SatItem>>>().apply {
addSource(itemsWithQuery) { value -> this.value = value }
}
private var shouldSelectAll = true
val satData: LiveData<Result<List<SatItem>>> = _satData
val satData: LiveData<DataState<List<SatItem>>> = _satData
fun updateEntriesFromFile(uri: Uri) {
viewModelScope.launch {
_satData.value = Result.InProgress
viewModelScope.launch(coroutineHandler) {
_satData.value = DataState.Loading
runCatching {
resolver.openInputStream(uri)?.use { stream ->
satelliteRepo.updateEntriesFromFile(stream)
}
}.onFailure { _satData.value = Result.Error(it) }
}.onFailure { _satData.value = DataState.Error(it) }
}
}
fun updateEntriesFromWeb(sources: List<String>) {
viewModelScope.launch {
_satData.value = Result.InProgress
try {
viewModelScope.launch(coroutineHandler) {
_satData.value = DataState.Loading
preferences.saveTleSources(sources)
satelliteRepo.updateEntriesFromWeb(sources)
} catch (exception: Exception) {
_satData.value = Result.Error(exception)
}
}
}
fun selectCurrentItems() {
val currentValue = _satData.value
if (currentValue is Result.Success) {
if (currentValue is DataState.Success) {
updateSelection(currentValue.data.map { it.catNum }, shouldSelectAll)
shouldSelectAll = shouldSelectAll.not()
}
@@ -30,7 +30,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.FragmentPassesBinding
import com.rtbishop.look4sat.domain.SatPass
import com.rtbishop.look4sat.framework.model.Result
import com.rtbishop.look4sat.framework.model.DataState
import com.rtbishop.look4sat.utility.RecyclerDivider
import com.rtbishop.look4sat.utility.navigateSafe
import com.rtbishop.look4sat.utility.toTimerString
@@ -73,21 +73,21 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
}
private fun handleNewPasses(
result: Result<List<SatPass>>,
dataState: DataState<List<SatPass>>,
passesAdapter: PassesAdapter,
binding: FragmentPassesBinding
) {
when (result) {
is Result.Success -> {
passesAdapter.submitList(result.data)
when (dataState) {
is DataState.Success -> {
passesAdapter.submitList(dataState.data)
binding.apply {
passesError.visibility = View.INVISIBLE
passesProgress.visibility = View.INVISIBLE
passesRecycler.visibility = View.VISIBLE
}
tickMainTimer(result.data, binding)
tickMainTimer(dataState.data, binding)
}
is Result.InProgress -> {
is DataState.Loading -> {
binding.apply {
passesTimer.text = 0L.toTimerString()
passesError.visibility = View.INVISIBLE
@@ -95,7 +95,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
passesProgress.visibility = View.VISIBLE
}
}
is Result.Error -> {
is DataState.Error -> {
binding.apply {
passesTimer.text = 0L.toTimerString()
passesProgress.visibility = View.INVISIBLE
@@ -25,7 +25,7 @@ import com.rtbishop.look4sat.data.Preferences
import com.rtbishop.look4sat.data.SatelliteRepo
import com.rtbishop.look4sat.domain.Predictor
import com.rtbishop.look4sat.domain.SatPass
import com.rtbishop.look4sat.framework.model.Result
import com.rtbishop.look4sat.framework.model.DataState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.collect
@@ -39,16 +39,16 @@ class PassesViewModel @Inject constructor(
private val preferences: Preferences
) : ViewModel() {
private val _passes = MutableLiveData<Result<List<SatPass>>>(Result.InProgress)
private val _passes = MutableLiveData<DataState<List<SatPass>>>(DataState.Loading)
private val _isFirstLaunchDone = MutableLiveData<Boolean>()
private var passesProcessing: Job? = null
val passes: LiveData<Result<List<SatPass>>> = _passes
val passes: LiveData<DataState<List<SatPass>>> = _passes
val isFirstLaunchDone: LiveData<Boolean> = _isFirstLaunchDone
init {
if (preferences.isSetupDone()) {
viewModelScope.launch {
_passes.postValue(Result.InProgress)
_passes.postValue(DataState.Loading)
val dateNow = Date()
val satellites = satelliteRepo.getSelectedSatellites()
val stationPos = preferences.loadStationPosition()
@@ -70,7 +70,7 @@ class PassesViewModel @Inject constructor(
fun triggerInitialSetup() {
preferences.updatePositionFromGPS()
viewModelScope.launch {
_passes.postValue(Result.InProgress)
_passes.postValue(DataState.Loading)
val defaultCatNums = listOf(43700, 25544, 25338, 28654, 33591, 40069, 27607, 24278)
val dateNow = Date()
val satellites = satelliteRepo.getSelectedSatellites()
@@ -87,7 +87,7 @@ class PassesViewModel @Inject constructor(
fun forceCalculation() {
viewModelScope.launch {
_passes.postValue(Result.InProgress)
_passes.postValue(DataState.Loading)
passesProcessing?.cancelAndJoin()
val dateNow = Date()
val satellites = satelliteRepo.getSelectedSatellites()
@@ -117,7 +117,7 @@ class PassesViewModel @Inject constructor(
}
}
currentPasses = currentPasses.filter { it.progress < 100 }
_passes.postValue(Result.Success(currentPasses.map { it.copy() }))
_passes.postValue(DataState.Success(currentPasses.map { it.copy() }))
delay(1000)
}
}
+2 -2
View File
@@ -5,12 +5,12 @@ buildscript {
coroutines_version = '1.5.2-native-mt'
material_version = '1.4.0'
splash_screen_version = '1.0.0-alpha01'
constraint_layout_version = '2.1.0'
constraint_layout_version = '2.1.1'
lifecycle_version = '2.3.1'
navigation_version = '2.3.5'
preference_version = '1.1.1'
room_version = '2.3.0'
hilt_version = '2.38.1'
hilt_version = '2.39'
retrofit_version = '2.9.0'
osmdroid_version = '6.1.11'
timber_version = '5.0.1'