Update: Replace CursorOwner's de-/attaching with VM's fillList

This commit is contained in:
machiav3lli
2022-01-03 23:36:04 +01:00
parent bedf5cad3f
commit 3082e7153d
7 changed files with 178 additions and 58 deletions

View File

@ -234,35 +234,6 @@ class MainActivityX : AppCompatActivity(), LoaderManager.LoaderCallbacks<Cursor>
syncConnection.binder?.setUpdateNotificationBlocker(blockerFragment)
}
fun attachCursorOwner(callback: CursorOwner.Callback, request: CursorOwner.Request) {
val oldActiveRequest = viewModel.activeRequests[request.id]
if (oldActiveRequest?.callback != null &&
oldActiveRequest.callback != callback && oldActiveRequest.cursor != null
) {
oldActiveRequest.callback.onCursorData(oldActiveRequest.request, null)
}
val cursor = if (oldActiveRequest?.request == request && oldActiveRequest.cursor != null) {
callback.onCursorData(request, oldActiveRequest.cursor)
oldActiveRequest.cursor
} else {
null
}
viewModel.activeRequests[request.id] = CursorOwner.ActiveRequest(request, callback, cursor)
if (cursor == null) {
LoaderManager.getInstance(this).restartLoader(request.id, null, this)
}
}
fun detachCursorOwner(callback: CursorOwner.Callback) {
for (id in viewModel.activeRequests.keys) {
val activeRequest = viewModel.activeRequests[id]!!
if (activeRequest.callback == callback) {
viewModel.activeRequests[id] = activeRequest.copy(callback = null)
}
}
}
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
val request = viewModel.activeRequests[id]!!.request
return QueryLoader(this) {

View File

@ -59,7 +59,7 @@ class ExploreFragment : MainNavFragmentX(), CursorOwner.Callback {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivityX.attachCursorOwner(this, viewModel.request(source))
viewModel.fillList(source)
viewModel.db.repositoryDao.allFlowable
.observeOn(Schedulers.io())
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }
@ -68,12 +68,6 @@ class ExploreFragment : MainNavFragmentX(), CursorOwner.Callback {
.subscribe { repositories = it }
}
override fun onDestroyView() {
super.onDestroyView()
mainActivityX.detachCursorOwner(this)
}
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
(binding.recyclerView.adapter as? AppListAdapter)?.apply {
this.cursor = cursor

View File

@ -72,7 +72,7 @@ class InstalledFragment : MainNavFragmentX(), CursorOwner.Callback {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivityX.attachCursorOwner(this, viewModel.request(source))
viewModel.fillList(source)
viewModel.db.repositoryDao.allFlowable
.observeOn(Schedulers.io())
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }
@ -81,12 +81,6 @@ class InstalledFragment : MainNavFragmentX(), CursorOwner.Callback {
.subscribe { repositories = it }
}
override fun onDestroyView() {
super.onDestroyView()
mainActivityX.detachCursorOwner(this)
}
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
// TODO get a list instead of the cursor
// TODO use LiveData and observers instead of listeners

View File

@ -72,7 +72,7 @@ class LatestFragment : MainNavFragmentX(), CursorOwner.Callback {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivityX.attachCursorOwner(this, viewModel.request(source))
viewModel.fillList(source)
viewModel.db.repositoryDao.allFlowable
.observeOn(Schedulers.io())
.flatMapSingle { list -> RxUtils.querySingle { list.mapNotNull { it.trueData } } }
@ -81,12 +81,6 @@ class LatestFragment : MainNavFragmentX(), CursorOwner.Callback {
.subscribe { repositories = it }
}
override fun onDestroyView() {
super.onDestroyView()
mainActivityX.detachCursorOwner(this)
}
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
// TODO get a list instead of the cursor
// TODO use LiveData and observers instead of listeners

View File

@ -18,7 +18,7 @@ abstract class MainNavFragmentX : Fragment(), CursorOwner.Callback {
internal fun setSearchQuery(searchQuery: String) {
viewModel.setSearchQuery(searchQuery) {
if (view != null) {
mainActivityX.attachCursorOwner(this, viewModel.request(source))
viewModel.fillList(source)
}
}
}
@ -26,7 +26,7 @@ abstract class MainNavFragmentX : Fragment(), CursorOwner.Callback {
internal fun setSection(section: ProductItem.Section) {
viewModel.setSection(section) {
if (view != null) {
mainActivityX.attachCursorOwner(this, viewModel.request(source))
viewModel.fillList(source)
}
}
}
@ -34,7 +34,7 @@ abstract class MainNavFragmentX : Fragment(), CursorOwner.Callback {
internal fun setOrder(order: ProductItem.Order) {
viewModel.setOrder(order) {
if (view != null) {
mainActivityX.attachCursorOwner(this, viewModel.request(source))
viewModel.fillList(source)
}
}
}
@ -44,4 +44,37 @@ enum class Source(val titleResId: Int, val sections: Boolean, val order: Boolean
AVAILABLE(R.string.available, true, true),
INSTALLED(R.string.installed, false, true),
UPDATES(R.string.updates, false, false)
}
sealed class Request {
internal abstract val id: Int
data class ProductsAvailable(
val searchQuery: String, val section: ProductItem.Section,
val order: ProductItem.Order,
) : Request() {
override val id: Int
get() = 1
}
data class ProductsInstalled(
val searchQuery: String, val section: ProductItem.Section,
val order: ProductItem.Order,
) : Request() {
override val id: Int
get() = 2
}
data class ProductsUpdates(
val searchQuery: String, val section: ProductItem.Section,
val order: ProductItem.Order,
) : Request() {
override val id: Int
get() = 3
}
object Repositories : Request() {
override val id: Int
get() = 4
}
}

View File

@ -1,11 +1,13 @@
package com.looker.droidify.ui.viewmodels
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.looker.droidify.database.CursorOwner
import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.Product
import com.looker.droidify.entity.ProductItem
import com.looker.droidify.ui.fragments.Request
import com.looker.droidify.ui.fragments.Source
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
@ -13,6 +15,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MainNavFragmentViewModelX(val db: DatabaseX) : ViewModel() {
@ -37,7 +40,7 @@ class MainNavFragmentViewModelX(val db: DatabaseX) : ViewModel() {
started = SharingStarted.WhileSubscribed(5000)
)
fun request(source: Source): CursorOwner.Request {
fun request(source: Source): Request {
var mSearchQuery = ""
var mSections: ProductItem.Section = ProductItem.Section.All
var mOrder: ProductItem.Order = ProductItem.Order.NAME
@ -47,17 +50,17 @@ class MainNavFragmentViewModelX(val db: DatabaseX) : ViewModel() {
launch { order.collect { if (source.order) mOrder = it } }
}
return when (source) {
Source.AVAILABLE -> CursorOwner.Request.ProductsAvailable(
Source.AVAILABLE -> Request.ProductsAvailable(
mSearchQuery,
mSections,
mOrder
)
Source.INSTALLED -> CursorOwner.Request.ProductsInstalled(
Source.INSTALLED -> Request.ProductsInstalled(
mSearchQuery,
mSections,
mOrder
)
Source.UPDATES -> CursorOwner.Request.ProductsUpdates(
Source.UPDATES -> Request.ProductsUpdates(
mSearchQuery,
mSections,
mOrder
@ -65,6 +68,46 @@ class MainNavFragmentViewModelX(val db: DatabaseX) : ViewModel() {
}
}
var productsList = MediatorLiveData<MutableList<Product>>()
fun fillList(source: Source) {
viewModelScope.launch {
productsList.value = query(request(source))?.toMutableList()
}
}
private suspend fun query(request: Request): List<Product>? {
return withContext(Dispatchers.IO) {
when (request) {
is Request.ProductsAvailable -> db.productDao
.queryList(
installed = false,
updates = false,
searchQuery = request.searchQuery,
section = request.section,
order = request.order
)
is Request.ProductsInstalled -> db.productDao
.queryList(
installed = true,
updates = false,
searchQuery = request.searchQuery,
section = request.section,
order = request.order
)
is Request.ProductsUpdates -> db.productDao
.queryList(
installed = true,
updates = true,
searchQuery = request.searchQuery,
section = request.section,
order = request.order
)
else -> listOf()
}
}
}
fun setSection(newSection: ProductItem.Section, perform: () -> Unit) {
viewModelScope.launch {
if (newSection != sections.value) {