Switch ChangelogFragment/ChangelogViewModel to use 'liveDataLoader'
This commit is contained in:
parent
3cd28c5b2c
commit
b7cfacd3f7
2 changed files with 14 additions and 77 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue