Skip to content

Commit

Permalink
refactor ui state handling - simplified view logic
Browse files Browse the repository at this point in the history
update target jdk to 11

bump library versions to latest available
  • Loading branch information
llopisdon committed Aug 21, 2021
1 parent e4dbeff commit 746c977
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 74 deletions.
22 changes: 11 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '11'
}
buildFeatures {
viewBinding true
Expand All @@ -46,16 +46,16 @@ android {
dependencies {

implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

def lifecycle_version = "2.4.0-alpha02"
def lifecycle_version = "2.4.0-alpha03"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
Expand All @@ -82,7 +82,7 @@ dependencies {

implementation "org.jetbrains.kotlinx:kotlinx-datetime:0.2.1"

implementation "io.coil-kt:coil:1.2.2"
implementation "io.coil-kt:coil:1.3.1"

implementation 'com.github.Baseflow:PhotoView:2.3.0'
}
41 changes: 20 additions & 21 deletions app/src/main/java/com/machineinteractive/apodktm/ApodViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,12 @@ class ApodViewModel @Inject constructor(private val repository: ApodRepository)

private val curDate = MutableStateFlow(maxDate)
private var pickerCurDate = maxDate
val apods: Flow<List<Apod>> = curDate.flatMapLatest {
@ExperimentalCoroutinesApi
private val apods: Flow<List<Apod>> = curDate.flatMapLatest {
repository.getApodsForCurMonth(it)
}.stateIn(
viewModelScope,
SharingStarted.Eagerly,
emptyList()
)
}

private val _apodListUiState = MutableStateFlow<ApodListUiState>(ApodListUiState.Idle)
private val _apodListUiState = MutableStateFlow(ApodListUiState())
val apodListUiState: StateFlow<ApodListUiState> = _apodListUiState

private val _selectedApod: MutableStateFlow<Apod?> = MutableStateFlow(null)
Expand All @@ -38,6 +35,12 @@ class ApodViewModel @Inject constructor(private val repository: ApodRepository)

init {
Log.d(TAG, "ApodViewModel.init...")
viewModelScope.launch {
apods.collect {
_apodListUiState.value = _apodListUiState.value.copy(apods = it)
}
}
fetchApods()
}

fun select(apod: Apod) {
Expand All @@ -49,25 +52,22 @@ class ApodViewModel @Inject constructor(private val repository: ApodRepository)
fun fetchApods() {
Log.d(TAG, "ApodViewModel.fetchApods - curDate: ${curDate.value} ...")
curJob = viewModelScope.launch(Dispatchers.IO) {
if (!isActive) return@launch
var hasApods = repository.curMonthHasApods(curDate.value)
Log.d(TAG, "hasApods: $hasApods")
if (!isActive) return@launch
if (repository.needsUpdate(curDate.value)) {
if (!isActive) return@launch
var hasApods = repository.curMonthHasApods(curDate.value)
Log.d(TAG, "hasApods: $hasApods")
if (!hasApods) {
_apodListUiState.value = ApodListUiState.Loading
_apodListUiState.value = _apodListUiState.value.copy(loading = true)
}
when (val result = repository.updateApodsForCurMonth(curDate.value)) {
is ApodResult.Error -> {
hasApods = repository.curMonthHasApods(curDate.value)
_apodListUiState.value = ApodListUiState.Error(hasApods, result)
_apodListUiState.value = _apodListUiState.value.copy(error = result)
return@launch
}
}
}
hasApods = repository.curMonthHasApods(curDate.value)
_apodListUiState.value = ApodListUiState.Success(hasApods)
_apodListUiState.value = _apodListUiState.value.copy(loading = false)
}
}

Expand Down Expand Up @@ -189,9 +189,8 @@ data class BottomNavBarUiState(

data class PickerUiState(val today: LocalDate, val curPickerDate: LocalDate)

sealed class ApodListUiState {
object Idle : ApodListUiState()
object Loading : ApodListUiState()
class Error(val hasApods: Boolean, val error: ApodResult.Error) : ApodListUiState()
class Success(val hasApods: Boolean) : ApodListUiState()
}
data class ApodListUiState(
val loading: Boolean = false,
val error: ApodResult.Error? = null,
val apods: List<Apod> = emptyList()
)
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,6 @@ class ApodsListFragment : Fragment(), ApodAdapter.Listener {
updateUi(state)
}
}
launch {
viewModel.apods.collect {
adapter.submitList(it)
}
}
viewModel.fetchApods()
}
}
}
Expand All @@ -96,45 +90,36 @@ class ApodsListFragment : Fragment(), ApodAdapter.Listener {
}

private fun updateUi(state: ApodListUiState) {
when (state) {
is ApodListUiState.Idle -> {
// NO-OP
}
is ApodListUiState.Loading -> {
Log.d(TAG, "loading...")
showProgressBar(true)
adapter.submitList(emptyList())
binding.emptyText.visibility = View.INVISIBLE
}
is ApodListUiState.Error -> {
Log.d(TAG, "error...")
showProgressBar(false)
toggleEmptyState(state.hasApods)
snackbar = Snackbar.make(
binding.snackbarArea,
"${state.error.message}",
Snackbar.LENGTH_INDEFINITE
)
snackbar?.setAction(getString(R.string.retry)) {
snackbar?.dismiss()
snackbar = null
viewModel.fetchApods()
}
snackbar?.show()
}
is ApodListUiState.Success -> {
Log.d(TAG, "success...")
showProgressBar(false)
toggleEmptyState(state.hasApods)
showProgressBar(state.loading)

if (state.error != null) {
snackbar = Snackbar.make(
binding.snackbarArea,
"${state.error.message}",
Snackbar.LENGTH_INDEFINITE
)
snackbar?.setAction(getString(R.string.retry)) {
snackbar?.dismiss()
snackbar = null
viewModel.fetchApods()
}
snackbar?.show()
}
}

private fun toggleEmptyState(hasApods: Boolean) {
binding.emptyText.visibility = if (hasApods) {
View.INVISIBLE
adapter.submitList(state.apods)

if (state.apods.isEmpty() && !state.loading) {
toggleEmptyState(true)
} else {
toggleEmptyState(false)
}
}

private fun toggleEmptyState(value: Boolean) {
binding.emptyText.visibility = if (value) {
View.VISIBLE
} else {
View.INVISIBLE
}
}

Expand Down
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
kotlin_version = "1.5.10"
kotlin_version = "1.5.21"
nav_version = "2.3.5"
hilt_version = "2.37"
}
Expand All @@ -26,7 +26,6 @@ allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
maven { url 'https://jitpack.io' }
}
}
Expand Down

0 comments on commit 746c977

Please sign in to comment.