Switch ChangelogFragment/ChangelogViewModel to use 'liveDataLoader'

This commit is contained in:
cketti 2021-02-23 14:36:48 +01:00
parent 3cd28c5b2c
commit b7cfacd3f7
2 changed files with 14 additions and 77 deletions

View file

@ -5,12 +5,11 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.fsck.k9.ui.R
import com.fsck.k9.ui.base.loader.observeLoading
import de.cketti.changelog.ReleaseItem
import org.koin.android.ext.android.inject
@ -25,32 +24,15 @@ class ChangelogFragment : Fragment() {
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.changelogState.observe(viewLifecycleOwner, StateObserver(view))
}
val listView = view.findViewById<RecyclerView>(R.id.changelog_list)
class StateObserver(view: View) : Observer<ChangeLogState> {
private val loadingView: View = view.findViewById(R.id.changelog_loading)
private val errorView: View = view.findViewById(R.id.changelog_error)
private val listView: RecyclerView = view.findViewById(R.id.changelog_list)
private val allViews = setOf(loadingView, errorView, listView)
override fun onChanged(state: ChangeLogState?) {
when (state) {
is ChangeLogState.Loading -> loadingView.show()
is ChangeLogState.Error -> errorView.show()
is ChangeLogState.Data -> showChangelog(state.changeLog)
}
}
private fun showChangelog(changeLog: List<ReleaseItem>) {
viewModel.changelogState.observeLoading(
owner = viewLifecycleOwner,
loadingView = view.findViewById(R.id.changelog_loading),
errorView = view.findViewById(R.id.changelog_error),
dataView = listView
) { changeLog ->
listView.adapter = ChangelogAdapter(changeLog)
listView.show()
}
private fun View.show() {
for (view in allViews) {
view.isVisible = view === this
}
}
}
}

View file

@ -2,62 +2,17 @@ package com.fsck.k9.ui.changelog
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.LiveDataScope
import androidx.lifecycle.ViewModel
import androidx.lifecycle.liveData
import com.fsck.k9.ui.changelog.ChangeLogState.Data
import com.fsck.k9.ui.changelog.ChangeLogState.Error
import com.fsck.k9.ui.changelog.ChangeLogState.Loading
import com.fsck.k9.ui.base.loader.LoaderState
import com.fsck.k9.ui.base.loader.liveDataLoader
import de.cketti.changelog.ChangeLog
import de.cketti.changelog.ReleaseItem
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
private const val PROGRESS_BAR_DELAY = 500L
private typealias ChangeLogState = LoaderState<List<ReleaseItem>>
class ChangelogViewModel(private val context: Context) : ViewModel() {
val changelogState: LiveData<ChangeLogState> = liveData {
coroutineScope {
loadChangelog(coroutineScope = this)
}
}
private suspend fun LiveDataScope<ChangeLogState>.loadChangelog(coroutineScope: CoroutineScope) {
val job = coroutineScope.launch {
delay(PROGRESS_BAR_DELAY)
// Show progress bar if loading took longer than configured delay. If changelog data was loaded faster
// than that, this coroutine will have been canceled before the next line is executed.
emit(Loading)
}
val finalState = try {
val data = withContext(Dispatchers.IO) {
val changeLog = ChangeLog.newInstance(context)
changeLog.changeLog
}
Data(data)
} catch (e: Exception) {
Timber.e(e, "Error loading changelog")
Error
}
// Cancel job that emits Loading state
job.cancelAndJoin()
emit(finalState)
val changelogState: LiveData<ChangeLogState> = liveDataLoader {
val changeLog = ChangeLog.newInstance(context)
changeLog.changeLog
}
}
sealed class ChangeLogState {
object Loading : ChangeLogState()
object Error : ChangeLogState()
class Data(val changeLog: List<ReleaseItem>) : ChangeLogState()
}