简体   繁体   中英

Android: Paging3: Duplicates items

Problem : I get 40 items at the beginning of the list, then it starts to count from 11, and after this, everything is good. So, 1...40,11,12,13,...,300.

在此处输入图像描述

And when I scroll a lot to the bottom and then scroll up to see first items, the items have been changed to 1,2,...,10,1,2,...,10,1,2,...,10,11,12,...,300.


But, when I pass false to enablePlaceholders in the PagingConfig , when I scroll to the bottom, I see the issue as I said above(1,2,..,40, 11, ...,300) and suddenly the 40 items vanish and I only see 1,2,...,10 + 11 ,12,...,300(the correct way); And it doesn't change or get worse again.


ProductsPagingSource :

@Singleton
class ProductsPagingSource @Inject constructor(
    private val productsApi: ProductsApi
    //private val query: String
) : RxPagingSource<Int, RecyclerItem>() {

    override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int, RecyclerItem>> {
        val position = params.key ?: STARTING_PAGE_INDEX
        //val apiQuery = query

        return productsApi.getBeersList(position, params.loadSize)
            .subscribeOn(Schedulers.io())
            .map { listBeerResponse ->
                listBeerResponse.map { beerResponse ->
                    beerResponse.toDomain()
                }
            }
            .map { toLoadResult(it, position) }
            .onErrorReturn { LoadResult.Error(it) }
    }

    private fun toLoadResult(
        @NonNull response: List<RecyclerItem>,
        position: Int
    ): LoadResult<Int, RecyclerItem> {
        return LoadResult.Page(
            data = response,
            prevKey = if (position == STARTING_PAGE_INDEX) null else position - 1,
            nextKey = if (response.isEmpty()) null else position + 1,
            itemsBefore = LoadResult.Page.COUNT_UNDEFINED,
            itemsAfter = LoadResult.Page.COUNT_UNDEFINED
        )
    }

}

ProductsListRepositoryImpl :

@Singleton
class ProductsListRepositoryImpl @Inject constructor(
    private val pagingSource: ProductsPagingSource
) : ProductsListRepository {

    override fun getBeers(ids: String): Flowable<PagingData<RecyclerItem>> = Pager(
        config = PagingConfig(
            pageSize = 10,
            enablePlaceholders = true,
            maxSize = 30,
            prefetchDistance = 5,
            initialLoadSize = 40
        ),
        pagingSourceFactory = { pagingSource }
    ).flowable

}

ProductsListViewModel :

class ProductsListViewModel @ViewModelInject constructor(
    private val getBeersUseCase: GetBeersUseCase
) : BaseViewModel() {

    private val _ldProductsList: MutableLiveData<PagingData<RecyclerItem>> = MutableLiveData()
    val ldProductsList: LiveData<PagingData<RecyclerItem>> = _ldProductsList

    init {
        loading(true)
        getProducts("")
    }

    private fun getProducts(ids: String) {
        loading(false)
        getBeersUseCase(GetBeersParams(ids = ids))
            .cachedIn(viewModelScope)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                _ldProductsList.value = it
            }.addTo(compositeDisposable)
    }

}

ProductsListFragment :

@AndroidEntryPoint
class ProductsListFragment : Fragment(R.layout.fragment_product_list) {

    private val productsListViewModel: ProductsListViewModel by viewModels()

    private val productsListAdapter: ProductsListAdapter by lazy {
        ProductsListAdapter(::navigateToProductDetail)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setupRecycler()
        setupViewModel()
    }

    private fun setupRecycler() {
        itemErrorContainer.gone()
        productListRecyclerView.adapter = productsListAdapter
    }

    private fun setupViewModel() {
        productsListViewModel.run {

            observe(ldProductsList, ::addProductsList)

            observe(ldLoading, ::loadingUI)

            observe(ldFailure, ::handleFailure)

        }
    }

    private fun addProductsList(productsList: PagingData<RecyclerItem>) {
        loadingUI(false)
        productListRecyclerView.visible()
        productsListAdapter.submitData(lifecycle, productsList)
    }
...

BASE_DIFF_CALLBACK :

val BASE_DIFF_CALLBACK = object : DiffUtil.ItemCallback<RecyclerItem>() {

    override fun areItemsTheSame(oldItem: RecyclerItem, newItem: RecyclerItem): Boolean {
        return oldItem.id == newItem.id
    }

    override fun areContentsTheSame(oldItem: RecyclerItem, newItem: RecyclerItem): Boolean {
        return oldItem == newItem
    }

}

BasePagedListAdapter :

abstract class BasePagedListAdapter(
    vararg types: Cell<RecyclerItem>,
    private val onItemClick: (RecyclerItem, ImageView) -> Unit
) : PagingDataAdapter<RecyclerItem, RecyclerView.ViewHolder>(BASE_DIFF_CALLBACK) {

    private val cellTypes: CellTypes<RecyclerItem> = CellTypes(*types)

    override fun getItemViewType(position: Int): Int {
        getItem(position).let {
            return cellTypes.of(it).type()
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return cellTypes.of(viewType).holder(parent)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        getItem(position).let {
            cellTypes.of(it).bind(holder, it, onItemClick)
        }
    }

}

I had to set the same number for pageSize and initialLoadSize . Also, I had to set the enablePlaceholders to false .

config = PagingConfig(
            pageSize = 10,
            enablePlaceholders = false,
            maxSize = 30,
            prefetchDistance = 5,
            initialLoadSize = 10
        ),

But still, I want to know if it's the normal way? If yes, I couldn't find anywhere point to this, If not? why's that? Why initialLoadSize can not have value more than the pageSize ?, As we can see, the default value for the initialLoadSize is:

internal const val DEFAULT_INITIAL_PAGE_MULTIPLIER = 3
val initialLoadSize: Int = pageSize * DEFAULT_INITIAL_PAGE_MULTIPLIER,

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM