From 8134db90d6e8c181b07d62f16a618ea9551cd5ea Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Wed, 10 Mar 2021 22:27:41 +0000 Subject: [PATCH] Swapped SingleLiveEvent for MutableStateFlow --- .../java/com/rtbishop/look4sat/data/Event.kt | 34 ----------- .../rtbishop/look4sat/ui/SharedViewModel.kt | 56 +++++++++++-------- .../ui/entriesScreen/EntriesFragment.kt | 24 ++++---- .../look4sat/ui/mapScreen/MapFragment.kt | 2 +- .../ui/passesScreen/PassesFragment.kt | 2 +- .../look4sat/ui/polarScreen/PolarFragment.kt | 2 +- build.gradle | 2 +- 7 files changed, 49 insertions(+), 73 deletions(-) delete mode 100644 app/src/main/java/com/rtbishop/look4sat/data/Event.kt diff --git a/app/src/main/java/com/rtbishop/look4sat/data/Event.kt b/app/src/main/java/com/rtbishop/look4sat/data/Event.kt deleted file mode 100644 index 6ac7a260..00000000 --- a/app/src/main/java/com/rtbishop/look4sat/data/Event.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Look4Sat. Amateur radio satellite tracker and pass predictor. - * Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.rtbishop.look4sat.data - -class Event(private val content: T) { - - private var hasBeenHandled = false - - fun getContentIfNotHandled(): T? { - return if (hasBeenHandled) { - null - } else { - hasBeenHandled = true - content - } - } - - fun peekContent(): T = content -} \ No newline at end of file diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt index 52a60a22..ec0cb20a 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/SharedViewModel.kt @@ -20,13 +20,18 @@ package com.rtbishop.look4sat.ui import android.net.Uri import androidx.lifecycle.* import com.github.amsacode.predict4java.Satellite -import com.rtbishop.look4sat.data.* +import com.rtbishop.look4sat.data.Result +import com.rtbishop.look4sat.data.SatItem +import com.rtbishop.look4sat.data.SatPass +import com.rtbishop.look4sat.data.TleSource import com.rtbishop.look4sat.repository.PrefsRepo import com.rtbishop.look4sat.repository.SatelliteRepo import com.rtbishop.look4sat.utility.getPredictor import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import java.util.* import javax.inject.Inject @@ -37,18 +42,21 @@ class SharedViewModel @Inject constructor( private val satelliteRepo: SatelliteRepo, ) : ViewModel() { - private val _passes = MutableLiveData>>() - private val _appEvent = MutableLiveData>() + private val _passes = MutableStateFlow>>(Result.InProgress) + val passes: LiveData>> = _passes.asLiveData() + + private val _satData = MutableStateFlow>>(Result.InProgress) + val satData: LiveData>> = _satData.asLiveData() init { if (prefsRepo.isFirstLaunch()) { updateDefaultSourcesAndEntries() prefsRepo.setFirstLaunchDone() } + loadDataFromDb() calculatePasses() } - fun getAppEvent(): LiveData> = _appEvent fun getAppTimer() = liveData { while (true) { emit(System.currentTimeMillis()) @@ -57,10 +65,7 @@ class SharedViewModel @Inject constructor( } fun getSources() = prefsRepo.loadTleSources() - fun getSatItems() = satelliteRepo.getSatItems().asLiveData() - fun getPasses(): LiveData>> = _passes - fun getTransmittersForSat(satId: Int) = - satelliteRepo.getTransmittersForSat(satId).asLiveData() + fun getTransmittersForSat(satId: Int) = satelliteRepo.getTransmittersForSat(satId).asLiveData() fun calculatePasses(dateNow: Date = Date(System.currentTimeMillis())) { _passes.value = Result.InProgress @@ -70,30 +75,30 @@ class SharedViewModel @Inject constructor( passes.addAll(getPasses(satellite, dateNow)) } val filteredPasses = sortList(passes, dateNow) - _passes.postValue(Result.Success(filteredPasses)) + _passes.value = Result.Success(filteredPasses) } } - + fun updateEntriesFromFile(uri: Uri) { - postAppEvent(Event(0)) + _satData.value = Result.InProgress viewModelScope.launch { try { satelliteRepo.updateEntriesFromFile(uri) } catch (exception: Exception) { - postAppEvent(Event(1)) + _satData.value = Result.Error(exception) } } } - - fun updateEntriesFromSources(sources: List) { - postAppEvent(Event(0)) + + fun updateEntriesFromSources(sources: List = prefsRepo.loadTleSources()) { + _satData.value = Result.InProgress viewModelScope.launch { try { prefsRepo.saveTleSources(sources) satelliteRepo.updateEntriesFromWeb(sources) satelliteRepo.updateTransmitters() } catch (exception: Exception) { - postAppEvent(Event(1)) + _satData.value = Result.Error(exception) } } } @@ -107,10 +112,6 @@ class SharedViewModel @Inject constructor( } } - private fun postAppEvent(event: Event) { - _appEvent.value = event - } - private fun getPasses(satellite: Satellite, dateNow: Date): MutableList { val predictor = satellite.getPredictor(prefsRepo.getStationPosition()) val passes = predictor.getPasses(dateNow, prefsRepo.getHoursAhead(), true) @@ -130,8 +131,19 @@ class SharedViewModel @Inject constructor( passes.sortBy { it.pass.startTime } return passes } - + + private fun loadDataFromDb() { + _satData.value = Result.InProgress + viewModelScope.launch { + satelliteRepo.getSatItems().collect { satItems: List -> + if (satItems.isNotEmpty()) { + _satData.value = Result.Success(satItems) + } + } + } + } + private fun updateDefaultSourcesAndEntries() { - updateEntriesFromSources(prefsRepo.loadTleSources()) + updateEntriesFromSources() } } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt index ee278cc2..ccd5cff9 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/entriesScreen/EntriesFragment.kt @@ -27,6 +27,7 @@ import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.snackbar.Snackbar import com.rtbishop.look4sat.R +import com.rtbishop.look4sat.data.Result import com.rtbishop.look4sat.databinding.FragmentEntriesBinding import com.rtbishop.look4sat.ui.SharedViewModel import com.rtbishop.look4sat.utility.RecyclerDivider @@ -70,19 +71,16 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) { } private fun setupObservers() { - setLoading() - viewModel.getSatItems().observe(viewLifecycleOwner, { satItems -> - if (satItems.isNullOrEmpty()) { - setError() - } else { - entriesAdapter?.setItems(satItems) - setLoaded() - } - }) - viewModel.getAppEvent().observe(viewLifecycleOwner, { event -> - event.getContentIfNotHandled()?.let { content -> - if (content == 0) setLoading() - else if (content == 1) { + viewModel.satData.observe(viewLifecycleOwner, { result -> + when (result) { + is Result.Success -> { + entriesAdapter?.setItems(result.data) + setLoaded() + } + is Result.InProgress -> { + setLoading() + } + is Result.Error -> { val errorMsg = getString(R.string.entries_update_error) Snackbar.make(requireView(), errorMsg, Snackbar.LENGTH_SHORT).show() entriesAdapter?.let { adapter -> diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/mapScreen/MapFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/mapScreen/MapFragment.kt index 0f578a63..db1d28e2 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/mapScreen/MapFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/mapScreen/MapFragment.kt @@ -83,7 +83,7 @@ class MapFragment : Fragment(R.layout.fragment_map) { private fun setupObservers() { mapViewModel.getGSP().observe(viewLifecycleOwner, { setupPosOverlay(it) }) - sharedViewModel.getPasses().observe(viewLifecycleOwner, { + sharedViewModel.passes.observe(viewLifecycleOwner, { if (it is Result.Success && it.data.isNotEmpty()) { mapViewModel.setPasses(it.data) binding.fabPrev.setOnClickListener { mapViewModel.scrollSelection(true) } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt index d2c5f2b9..45a595d2 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt @@ -54,7 +54,7 @@ class PassesFragment : Fragment(R.layout.fragment_passes) { } private fun setupObservers() { - viewModel.getPasses().observe(viewLifecycleOwner, { result -> + viewModel.passes.observe(viewLifecycleOwner, { result -> if (result is Result.Success) { if (result.data.isEmpty()) { binding?.apply { diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt index 76ed6150..97773f41 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt @@ -97,7 +97,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener { } private fun observePasses() { - viewModel.getPasses().observe(viewLifecycleOwner, { result -> + viewModel.passes.observe(viewLifecycleOwner, { result -> if (result is Result.Success) { satPass = result.data[requireArguments().getInt("index")] polarView = PolarView(requireContext()).apply { setPass(satPass) } diff --git a/build.gradle b/build.gradle index 325e27e0..a784437d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { material_version = '1.3.0' constraint_layout_version = '2.0.4' lifecycle_version = '2.3.0' - navigation_version = '2.3.3' + navigation_version = '2.3.4' preference_version = '1.1.1' room_version = '2.2.6' hilt_version = '2.33-beta'