Improve: Move more logic to ViewModel

This commit is contained in:
LooKeR 2021-11-10 14:57:32 +05:30
parent 9afcd3661f
commit 65541e7f4f
2 changed files with 45 additions and 71 deletions

View File

@ -2,7 +2,6 @@ package com.looker.droidify.ui.appsList
import android.database.Cursor
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -22,7 +21,7 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
class AppListFragment() : BaseFragment(), CursorOwner.Callback {
@ -30,7 +29,6 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
companion object {
private const val EXTRA_SOURCE = "source"
private const val STATE_LAYOUT_MANAGER = "layoutManager"
}
enum class Source(val titleResId: Int, val sections: Boolean, val order: Boolean) {
@ -48,51 +46,10 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
val source: Source
get() = requireArguments().getString(EXTRA_SOURCE)!!.let(Source::valueOf)
private val searchQuery: String
get() {
var _searchQuery = ""
lifecycleScope.launchWhenCreated { viewModel.searchQuery.collect { _searchQuery = it } }
return _searchQuery
}
private val section: ProductItem.Section
get() {
var _section: ProductItem.Section = ProductItem.Section.All
lifecycleScope.launchWhenCreated { viewModel.sections.collect { _section = it } }
return _section
}
private val order: ProductItem.Order
get() {
var _order: ProductItem.Order = ProductItem.Order.LAST_UPDATE
lifecycleScope.launchWhenCreated { viewModel.order.collect { _order = it } }
return _order
}
private var layoutManagerState: Parcelable? = null
private var recyclerView: RecyclerView? = null
private var repositoriesDisposable: Disposable? = null
private val request: CursorOwner.Request
get() {
val searchQuery = searchQuery
val section = if (source.sections) section else ProductItem.Section.All
val order = if (source.order) order else ProductItem.Order.NAME
return when (source) {
Source.AVAILABLE -> CursorOwner.Request.ProductsAvailable(
searchQuery,
section,
order
)
Source.INSTALLED -> CursorOwner.Request.ProductsInstalled(
searchQuery,
section,
order
)
Source.UPDATES -> CursorOwner.Request.ProductsUpdates(searchQuery, section, order)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -114,14 +71,13 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
layoutManagerState = savedInstanceState?.getParcelable(STATE_LAYOUT_MANAGER)
screenActivity.cursorOwner.attach(this, request)
screenActivity.cursorOwner.attach(this, viewModel.request(source))
repositoriesDisposable = Observable.just(Unit)
.concatWith(Database.observable(Database.Subject.Repositories))
.observeOn(Schedulers.io())
.flatMapSingle { RxUtils.querySingle { Database.RepositoryAdapter.getAll(it) } }
.map { it.asSequence().map { Pair(it.id, it) }.toMap() }
.map { list -> list.asSequence().map { Pair(it.id, it) }.toMap() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { (recyclerView?.adapter as? ProductsAdapter)?.repositories = it }
}
@ -136,35 +92,28 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
repositoriesDisposable = null
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
(layoutManagerState ?: recyclerView?.layoutManager?.onSaveInstanceState())
?.let { outState.putParcelable(STATE_LAYOUT_MANAGER, it) }
}
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
(recyclerView?.adapter as? ProductsAdapter)?.apply {
this.cursor = cursor
emptyText = when {
cursor == null -> ""
searchQuery.isNotEmpty() -> getString(R.string.no_matching_applications_found)
else -> when (source) {
Source.AVAILABLE -> getString(R.string.no_applications_available)
Source.INSTALLED -> getString(R.string.no_applications_installed)
Source.UPDATES -> getString(R.string.all_applications_up_to_date)
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
emptyText = when {
cursor == null -> ""
viewModel.searchQuery.first()
.isNotEmpty() -> getString(R.string.no_matching_applications_found)
else -> when (source) {
Source.AVAILABLE -> getString(R.string.no_applications_available)
Source.INSTALLED -> getString(R.string.no_applications_installed)
Source.UPDATES -> getString(R.string.all_applications_up_to_date)
}
}
}
}
layoutManagerState?.let {
layoutManagerState = null
recyclerView?.layoutManager?.onRestoreInstanceState(it)
}
}
internal fun setSearchQuery(searchQuery: String) {
viewModel.setSearchQuery(searchQuery) {
if (view != null) {
screenActivity.cursorOwner.attach(this, request)
screenActivity.cursorOwner.attach(this, viewModel.request(source))
}
}
}
@ -172,7 +121,7 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
internal fun setSection(section: ProductItem.Section) {
viewModel.setSection(section) {
if (view != null) {
screenActivity.cursorOwner.attach(this, request)
screenActivity.cursorOwner.attach(this, viewModel.request(source))
}
}
}
@ -180,7 +129,7 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
internal fun setOrder(order: ProductItem.Order) {
viewModel.setOrder(order) {
if (view != null) {
screenActivity.cursorOwner.attach(this, request)
screenActivity.cursorOwner.attach(this, viewModel.request(source))
}
}
}

View File

@ -2,12 +2,10 @@ package com.looker.droidify.ui.appsList
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.looker.droidify.database.CursorOwner
import com.looker.droidify.entity.ProductItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
class AppListViewModel : ViewModel() {
@ -21,6 +19,7 @@ class AppListViewModel : ViewModel() {
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000)
)
val sections: StateFlow<ProductItem.Section> = _sections.stateIn(
initialValue = ProductItem.Section.All,
scope = viewModelScope,
@ -32,6 +31,32 @@ class AppListViewModel : ViewModel() {
started = SharingStarted.WhileSubscribed(5000)
)
fun request(source: AppListFragment.Source): CursorOwner.Request {
var mSearchQuery = ""
var mSections: ProductItem.Section = ProductItem.Section.All
var mOrder: ProductItem.Order = ProductItem.Order.NAME
viewModelScope.launch { searchQuery.collect { if (source.sections) mSearchQuery = it } }
viewModelScope.launch { sections.collect { if (source.sections) mSections = it } }
viewModelScope.launch { order.collect { if (source.order) mOrder = it } }
return when (source) {
AppListFragment.Source.AVAILABLE -> CursorOwner.Request.ProductsAvailable(
mSearchQuery,
mSections,
mOrder
)
AppListFragment.Source.INSTALLED -> CursorOwner.Request.ProductsInstalled(
mSearchQuery,
mSections,
mOrder
)
AppListFragment.Source.UPDATES -> CursorOwner.Request.ProductsUpdates(
mSearchQuery,
mSections,
mOrder
)
}
}
fun setSection(newSection: ProductItem.Section, perform: () -> Unit) {
viewModelScope.launch(Dispatchers.Main) {
if (newSection != sections.value) {