mirror of
https://github.com/Aviortheking/Neo-Store.git
synced 2025-04-23 19:32:16 +00:00
Update: Migrate to Paged FastAdapter
This commit is contained in:
parent
f6ff3844ae
commit
edc0235119
@ -151,6 +151,7 @@ dependencies {
|
||||
implementation("com.mikepenz:fastadapter:5.6.0")
|
||||
implementation("com.mikepenz:fastadapter-extensions-diff:5.6.0")
|
||||
implementation("com.mikepenz:fastadapter-extensions-binding:5.6.0")
|
||||
implementation("com.mikepenz:fastadapter-extensions-paged:5.6.0")
|
||||
|
||||
// Coil
|
||||
implementation 'io.coil-kt:coil:1.4.0'
|
||||
|
@ -2,6 +2,7 @@ package com.looker.droidify.database
|
||||
|
||||
import android.database.Cursor
|
||||
import android.os.CancellationSignal
|
||||
import androidx.paging.DataSource
|
||||
import androidx.room.*
|
||||
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||
import androidx.sqlite.db.SupportSQLiteQuery
|
||||
@ -175,14 +176,13 @@ interface ProductDao : BaseDao<Product> {
|
||||
@RawQuery(observedEntities = [Product::class])
|
||||
fun queryList(
|
||||
query: SupportSQLiteQuery
|
||||
): List<Product>
|
||||
): DataSource.Factory<Int, Product>
|
||||
|
||||
// TODO optimize and simplify
|
||||
@Transaction
|
||||
fun queryList(
|
||||
installed: Boolean, updates: Boolean, searchQuery: String,
|
||||
section: ProductItem.Section, order: ProductItem.Order, numberOfItems: Int = 0
|
||||
): List<Product> {
|
||||
): DataSource.Factory<Int, Product> {
|
||||
val builder = QueryBuilder()
|
||||
|
||||
val signatureMatches = """installed.${ROW_SIGNATURE} IS NOT NULL AND
|
||||
|
@ -11,9 +11,13 @@ import com.looker.droidify.database.Product
|
||||
import com.looker.droidify.databinding.FragmentExploreXBinding
|
||||
import com.looker.droidify.entity.Repository
|
||||
import com.looker.droidify.ui.adapters.AppListAdapter
|
||||
import com.looker.droidify.ui.items.VAppItem
|
||||
import com.looker.droidify.ui.viewmodels.MainNavFragmentViewModelX
|
||||
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
||||
import com.looker.droidify.utility.RxUtils
|
||||
import com.looker.droidify.utility.extension.resources.getDrawableCompat
|
||||
import com.mikepenz.fastadapter.FastAdapter
|
||||
import com.mikepenz.fastadapter.paged.PagedModelAdapter
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||
@ -23,6 +27,8 @@ class ExploreFragment : MainNavFragmentX() {
|
||||
|
||||
override lateinit var viewModel: MainNavFragmentViewModelX
|
||||
private lateinit var binding: FragmentExploreXBinding
|
||||
private lateinit var appsItemAdapter: PagedModelAdapter<Product, VAppItem>
|
||||
private var appsFastAdapter: FastAdapter<VAppItem>? = null
|
||||
|
||||
override val source = Source.AVAILABLE
|
||||
|
||||
@ -40,13 +46,19 @@ class ExploreFragment : MainNavFragmentX() {
|
||||
viewModel = ViewModelProvider(this, viewModelFactory)
|
||||
.get(MainNavFragmentViewModelX::class.java)
|
||||
|
||||
appsItemAdapter = PagedModelAdapter<Product, VAppItem>(PRODUCT_ASYNC_DIFFER_CONFIG) {
|
||||
it.data_item?.let { item ->
|
||||
VAppItem(item, repositories[it.repository_id])
|
||||
}
|
||||
}
|
||||
|
||||
appsFastAdapter = FastAdapter.with(appsItemAdapter)
|
||||
appsFastAdapter?.setHasStableIds(true)
|
||||
binding.recyclerView.apply {
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
isMotionEventSplittingEnabled = false
|
||||
isVerticalScrollBarEnabled = false
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
setHasFixedSize(true)
|
||||
recycledViewPool.setMaxRecycledViews(AppListAdapter.ViewType.PRODUCT.ordinal, 30)
|
||||
adapter = AppListAdapter { mainActivityX.navigateProduct(it.packageName) }
|
||||
adapter = appsFastAdapter
|
||||
FastScrollerBuilder(this)
|
||||
.useMd2Style()
|
||||
.setThumbDrawable(this.context.getDrawableCompat(R.drawable.scrollbar_thumb))
|
||||
|
@ -8,16 +8,18 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.looker.droidify.R
|
||||
import com.looker.droidify.database.Product
|
||||
import com.looker.droidify.databinding.FragmentInstalledXBinding
|
||||
import com.looker.droidify.entity.ProductItem
|
||||
import com.looker.droidify.entity.Repository
|
||||
import com.looker.droidify.ui.adapters.AppListAdapter
|
||||
import com.looker.droidify.ui.items.HAppItem
|
||||
import com.looker.droidify.ui.items.VAppItem
|
||||
import com.looker.droidify.ui.viewmodels.MainNavFragmentViewModelX
|
||||
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
||||
import com.looker.droidify.utility.RxUtils
|
||||
import com.looker.droidify.utility.extension.resources.getDrawableCompat
|
||||
import com.mikepenz.fastadapter.FastAdapter
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter
|
||||
import com.mikepenz.fastadapter.paged.PagedModelAdapter
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||
@ -27,9 +29,9 @@ class InstalledFragment : MainNavFragmentX() {
|
||||
override lateinit var viewModel: MainNavFragmentViewModelX
|
||||
private lateinit var binding: FragmentInstalledXBinding
|
||||
|
||||
private val installedItemAdapter = ItemAdapter<VAppItem>()
|
||||
private lateinit var installedItemAdapter: PagedModelAdapter<Product, VAppItem>
|
||||
private var installedFastAdapter: FastAdapter<VAppItem>? = null
|
||||
private val updatedItemAdapter = ItemAdapter<HAppItem>()
|
||||
private lateinit var updatedItemAdapter: PagedModelAdapter<Product, HAppItem>
|
||||
private var updatedFastAdapter: FastAdapter<HAppItem>? = null
|
||||
|
||||
override val source = Source.INSTALLED
|
||||
@ -48,12 +50,23 @@ class InstalledFragment : MainNavFragmentX() {
|
||||
viewModel = ViewModelProvider(this, viewModelFactory)
|
||||
.get(MainNavFragmentViewModelX::class.java)
|
||||
|
||||
installedItemAdapter = PagedModelAdapter<Product, VAppItem>(PRODUCT_ASYNC_DIFFER_CONFIG) {
|
||||
it.data_item?.let { item ->
|
||||
VAppItem(item, repositories[it.repository_id])
|
||||
}
|
||||
}
|
||||
updatedItemAdapter = PagedModelAdapter<Product, HAppItem>(PRODUCT_ASYNC_DIFFER_CONFIG) {
|
||||
it.data_item?.let { item ->
|
||||
// TODO filter for only updated apps and add placeholder
|
||||
HAppItem(item, repositories[it.repository_id])
|
||||
}
|
||||
}
|
||||
|
||||
installedFastAdapter = FastAdapter.with(installedItemAdapter)
|
||||
installedFastAdapter?.setHasStableIds(true)
|
||||
binding.installedRecycler.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
isMotionEventSplittingEnabled = false
|
||||
isVerticalScrollBarEnabled = false
|
||||
recycledViewPool.setMaxRecycledViews(AppListAdapter.ViewType.PRODUCT.ordinal, 30)
|
||||
adapter = installedFastAdapter
|
||||
FastScrollerBuilder(this)
|
||||
.useMd2Style()
|
||||
@ -64,13 +77,8 @@ class InstalledFragment : MainNavFragmentX() {
|
||||
updatedFastAdapter?.setHasStableIds(true)
|
||||
binding.updatedRecycler.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
|
||||
isMotionEventSplittingEnabled = false
|
||||
isVerticalScrollBarEnabled = false
|
||||
recycledViewPool.setMaxRecycledViews(AppListAdapter.ViewType.PRODUCT.ordinal, 30)
|
||||
adapter = updatedFastAdapter
|
||||
FastScrollerBuilder(this)
|
||||
.useMd2Style()
|
||||
.setThumbDrawable(this.context.getDrawableCompat(R.drawable.scrollbar_thumb))
|
||||
.build()
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
@ -8,16 +8,18 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.looker.droidify.R
|
||||
import com.looker.droidify.database.Product
|
||||
import com.looker.droidify.databinding.FragmentLatestXBinding
|
||||
import com.looker.droidify.entity.ProductItem
|
||||
import com.looker.droidify.entity.Repository
|
||||
import com.looker.droidify.ui.adapters.AppListAdapter
|
||||
import com.looker.droidify.ui.items.HAppItem
|
||||
import com.looker.droidify.ui.items.VAppItem
|
||||
import com.looker.droidify.ui.viewmodels.MainNavFragmentViewModelX
|
||||
import com.looker.droidify.utility.PRODUCT_ASYNC_DIFFER_CONFIG
|
||||
import com.looker.droidify.utility.RxUtils
|
||||
import com.looker.droidify.utility.extension.resources.getDrawableCompat
|
||||
import com.mikepenz.fastadapter.FastAdapter
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter
|
||||
import com.mikepenz.fastadapter.paged.PagedModelAdapter
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import me.zhanghai.android.fastscroll.FastScrollerBuilder
|
||||
@ -27,11 +29,12 @@ class LatestFragment : MainNavFragmentX() {
|
||||
override lateinit var viewModel: MainNavFragmentViewModelX
|
||||
private lateinit var binding: FragmentLatestXBinding
|
||||
|
||||
private val updatedItemAdapter = ItemAdapter<VAppItem>()
|
||||
private lateinit var updatedItemAdapter: PagedModelAdapter<Product, VAppItem>
|
||||
private var updatedFastAdapter: FastAdapter<VAppItem>? = null
|
||||
private val newItemAdapter = ItemAdapter<HAppItem>()
|
||||
private lateinit var newItemAdapter: PagedModelAdapter<Product, HAppItem>
|
||||
private var newFastAdapter: FastAdapter<HAppItem>? = null
|
||||
|
||||
// TODO replace the source with one that get a certain amount of updated apps
|
||||
override val source = Source.AVAILABLE
|
||||
|
||||
private var repositories: Map<Long, Repository> = mapOf()
|
||||
@ -48,12 +51,23 @@ class LatestFragment : MainNavFragmentX() {
|
||||
viewModel = ViewModelProvider(this, viewModelFactory)
|
||||
.get(MainNavFragmentViewModelX::class.java)
|
||||
|
||||
updatedItemAdapter = PagedModelAdapter<Product, VAppItem>(PRODUCT_ASYNC_DIFFER_CONFIG) {
|
||||
it.data_item?.let { item ->
|
||||
VAppItem(item, repositories[it.repository_id])
|
||||
}
|
||||
}
|
||||
newItemAdapter = PagedModelAdapter<Product, HAppItem>(PRODUCT_ASYNC_DIFFER_CONFIG) {
|
||||
it.data_item?.let { item ->
|
||||
// TODO filter for only new apps and add placeholder
|
||||
HAppItem(item, repositories[it.repository_id])
|
||||
}
|
||||
}
|
||||
|
||||
updatedFastAdapter = FastAdapter.with(updatedItemAdapter)
|
||||
updatedFastAdapter?.setHasStableIds(true)
|
||||
binding.updatedRecycler.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
isMotionEventSplittingEnabled = false
|
||||
isVerticalScrollBarEnabled = false
|
||||
recycledViewPool.setMaxRecycledViews(AppListAdapter.ViewType.PRODUCT.ordinal, 30)
|
||||
adapter = updatedFastAdapter
|
||||
FastScrollerBuilder(this)
|
||||
.useMd2Style()
|
||||
@ -64,13 +78,8 @@ class LatestFragment : MainNavFragmentX() {
|
||||
newFastAdapter?.setHasStableIds(true)
|
||||
binding.newRecycler.apply {
|
||||
layoutManager = LinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
|
||||
isMotionEventSplittingEnabled = false
|
||||
isVerticalScrollBarEnabled = false
|
||||
recycledViewPool.setMaxRecycledViews(AppListAdapter.ViewType.PRODUCT.ordinal, 30)
|
||||
adapter = newFastAdapter
|
||||
FastScrollerBuilder(this)
|
||||
.useMd2Style()
|
||||
.setThumbDrawable(this.context.getDrawableCompat(R.drawable.scrollbar_thumb))
|
||||
.build()
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
@ -1,14 +1,18 @@
|
||||
package com.looker.droidify.ui.viewmodels
|
||||
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.paging.DataSource
|
||||
import androidx.paging.LivePagedListBuilder
|
||||
import androidx.paging.PagedList
|
||||
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.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@ -68,15 +72,36 @@ class MainNavFragmentViewModelX(val db: DatabaseX, source: Source) : ViewModel()
|
||||
}
|
||||
}
|
||||
|
||||
var productsList = MediatorLiveData<MutableList<Product>>()
|
||||
var productsList: LiveData<PagedList<Product>>
|
||||
|
||||
init {
|
||||
|
||||
val pagedListConfig = PagedList.Config.Builder()
|
||||
.setPageSize(30)
|
||||
.setPrefetchDistance(30)
|
||||
.setEnablePlaceholders(false)
|
||||
.build()
|
||||
val request = request(source)
|
||||
|
||||
productsList = LivePagedListBuilder(
|
||||
db.productDao.queryList(
|
||||
installed = request.installed,
|
||||
updates = request.updates,
|
||||
searchQuery = request.searchQuery,
|
||||
section = request.section,
|
||||
order = request.order,
|
||||
numberOfItems = request.numberOfItems
|
||||
), pagedListConfig
|
||||
).build()
|
||||
}
|
||||
|
||||
fun fillList(source: Source) {
|
||||
viewModelScope.launch {
|
||||
productsList.value = query(request(source))?.toMutableList()
|
||||
CoroutineScope(Dispatchers.Default).launch {
|
||||
// productsList = query(request(source))
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun query(request: Request): List<Product>? {
|
||||
private suspend fun query(request: Request): DataSource.Factory<Int, Product> {
|
||||
return withContext(Dispatchers.Default) {
|
||||
db.productDao
|
||||
.queryList(
|
||||
|
@ -10,6 +10,8 @@ import android.content.res.Configuration
|
||||
import android.database.Cursor
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.fasterxml.jackson.core.JsonParser
|
||||
import com.looker.droidify.*
|
||||
@ -234,4 +236,23 @@ fun jsonGenerate(callback: (JsonGenerator) -> Unit): ByteArray {
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
Json.factory.createGenerator(outputStream).use { it.writeDictionary(callback) }
|
||||
return outputStream.toByteArray()
|
||||
}
|
||||
}
|
||||
|
||||
val PRODUCT_ASYNC_DIFFER_CONFIG
|
||||
get() = AsyncDifferConfig.Builder(object :
|
||||
DiffUtil.ItemCallback<com.looker.droidify.database.Product>() {
|
||||
override fun areItemsTheSame(
|
||||
oldItem: com.looker.droidify.database.Product,
|
||||
newItem: com.looker.droidify.database.Product
|
||||
): Boolean {
|
||||
return oldItem.repository_id == newItem.repository_id
|
||||
&& oldItem.package_name == newItem.package_name
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: com.looker.droidify.database.Product,
|
||||
newItem: com.looker.droidify.database.Product
|
||||
): Boolean {
|
||||
return oldItem.data_item == newItem.data_item
|
||||
}
|
||||
}).build()
|
Loading…
x
Reference in New Issue
Block a user