mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-06-08 00:39:54 +00:00
Improve: Move more logic to ViewModel
This commit is contained in:
parent
9afcd3661f
commit
65541e7f4f
@ -2,7 +2,6 @@ package com.looker.droidify.ui.appsList
|
|||||||
|
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
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.core.Observable
|
||||||
import io.reactivex.rxjava3.disposables.Disposable
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
||||||
class AppListFragment() : BaseFragment(), CursorOwner.Callback {
|
class AppListFragment() : BaseFragment(), CursorOwner.Callback {
|
||||||
|
|
||||||
@ -30,7 +29,6 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val EXTRA_SOURCE = "source"
|
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) {
|
enum class Source(val titleResId: Int, val sections: Boolean, val order: Boolean) {
|
||||||
@ -48,51 +46,10 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
|
|||||||
val source: Source
|
val source: Source
|
||||||
get() = requireArguments().getString(EXTRA_SOURCE)!!.let(Source::valueOf)
|
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 recyclerView: RecyclerView? = null
|
||||||
|
|
||||||
private var repositoriesDisposable: Disposable? = 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(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
@ -114,14 +71,13 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
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)
|
repositoriesDisposable = Observable.just(Unit)
|
||||||
.concatWith(Database.observable(Database.Subject.Repositories))
|
.concatWith(Database.observable(Database.Subject.Repositories))
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.flatMapSingle { RxUtils.querySingle { Database.RepositoryAdapter.getAll(it) } }
|
.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())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe { (recyclerView?.adapter as? ProductsAdapter)?.repositories = it }
|
.subscribe { (recyclerView?.adapter as? ProductsAdapter)?.repositories = it }
|
||||||
}
|
}
|
||||||
@ -136,35 +92,28 @@ class AppListFragment() : BaseFragment(), CursorOwner.Callback {
|
|||||||
repositoriesDisposable = null
|
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?) {
|
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
|
||||||
(recyclerView?.adapter as? ProductsAdapter)?.apply {
|
(recyclerView?.adapter as? ProductsAdapter)?.apply {
|
||||||
this.cursor = cursor
|
this.cursor = cursor
|
||||||
emptyText = when {
|
viewLifecycleOwner.lifecycleScope.launchWhenCreated {
|
||||||
cursor == null -> ""
|
emptyText = when {
|
||||||
searchQuery.isNotEmpty() -> getString(R.string.no_matching_applications_found)
|
cursor == null -> ""
|
||||||
else -> when (source) {
|
viewModel.searchQuery.first()
|
||||||
Source.AVAILABLE -> getString(R.string.no_applications_available)
|
.isNotEmpty() -> getString(R.string.no_matching_applications_found)
|
||||||
Source.INSTALLED -> getString(R.string.no_applications_installed)
|
else -> when (source) {
|
||||||
Source.UPDATES -> getString(R.string.all_applications_up_to_date)
|
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) {
|
internal fun setSearchQuery(searchQuery: String) {
|
||||||
viewModel.setSearchQuery(searchQuery) {
|
viewModel.setSearchQuery(searchQuery) {
|
||||||
if (view != null) {
|
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) {
|
internal fun setSection(section: ProductItem.Section) {
|
||||||
viewModel.setSection(section) {
|
viewModel.setSection(section) {
|
||||||
if (view != null) {
|
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) {
|
internal fun setOrder(order: ProductItem.Order) {
|
||||||
viewModel.setOrder(order) {
|
viewModel.setOrder(order) {
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
screenActivity.cursorOwner.attach(this, request)
|
screenActivity.cursorOwner.attach(this, viewModel.request(source))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,10 @@ package com.looker.droidify.ui.appsList
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.looker.droidify.database.CursorOwner
|
||||||
import com.looker.droidify.entity.ProductItem
|
import com.looker.droidify.entity.ProductItem
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.stateIn
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class AppListViewModel : ViewModel() {
|
class AppListViewModel : ViewModel() {
|
||||||
@ -21,6 +19,7 @@ class AppListViewModel : ViewModel() {
|
|||||||
scope = viewModelScope,
|
scope = viewModelScope,
|
||||||
started = SharingStarted.WhileSubscribed(5000)
|
started = SharingStarted.WhileSubscribed(5000)
|
||||||
)
|
)
|
||||||
|
|
||||||
val sections: StateFlow<ProductItem.Section> = _sections.stateIn(
|
val sections: StateFlow<ProductItem.Section> = _sections.stateIn(
|
||||||
initialValue = ProductItem.Section.All,
|
initialValue = ProductItem.Section.All,
|
||||||
scope = viewModelScope,
|
scope = viewModelScope,
|
||||||
@ -32,6 +31,32 @@ class AppListViewModel : ViewModel() {
|
|||||||
started = SharingStarted.WhileSubscribed(5000)
|
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) {
|
fun setSection(newSection: ProductItem.Section, perform: () -> Unit) {
|
||||||
viewModelScope.launch(Dispatchers.Main) {
|
viewModelScope.launch(Dispatchers.Main) {
|
||||||
if (newSection != sections.value) {
|
if (newSection != sections.value) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user