Secondary encapsulation of paging data source and my current understanding

Keywords: Mobile Database Android Google network

To be honest, the definition of paging data source is too tedious, so it's encapsulated twice, without any intrusion, clean and neat. It's preserved for the time being, maybe it can be used in my life..

package com.lk.care.respository

import androidx.paging.DataSource
import androidx.paging.PageKeyedDataSource
import androidx.paging.PagedList
import androidx.paging.RxPagedListBuilder
import io.reactivex.schedulers.Schedulers

/**
 *  @author : william
 *  @createDate : 2020/5/28
 *
 *  @description :
 */


abstract class PagingDataSourceFactory<K, V> : DataSource.Factory<K, V>() {

    val cacheList = arrayListOf<V>()

    override fun create() = createDataSource()

    abstract fun createDataSource(): PageKeyedDataSource<K, V>

    companion object {
        fun <K, V> createRxPagedListBuilder(
            setInitResult: (
                params: PageKeyedDataSource.LoadInitialParams<K>,
                callback: PageKeyedDataSource.LoadInitialCallback<K, V>
            ) -> Unit,
            setAfterResult: (params: PageKeyedDataSource.LoadParams<K>, callback: PageKeyedDataSource.LoadCallback<K, V>) -> Unit,
            vararg setBeforeResult: (params: PageKeyedDataSource.LoadParams<K>, callback: PageKeyedDataSource.LoadCallback<K, V>) -> Unit,
            pageSize: Int = 20
        ) = RxPagedListBuilder(
            object : PagingDataSourceFactory<K, V>() {
                override fun createDataSource() = object : PageKeyedDataSource<K, V>() {
                    override fun loadInitial(
                        params: LoadInitialParams<K>,
                        callback: LoadInitialCallback<K, V>
                    ) {
                        setInitResult.invoke(params, callback)
                    }

                    override fun loadAfter(params: LoadParams<K>, callback: LoadCallback<K, V>) {
                        setAfterResult.invoke(params, callback)
                    }

                    override fun loadBefore(params: LoadParams<K>, callback: LoadCallback<K, V>) {
                        if (setBeforeResult.isNotEmpty()) {
                            for (function in setBeforeResult) {
                                function.invoke(params, callback)
                            }
                        }
                    }

                }
            },
            PagedList.Config.Builder()
                .setPageSize(pageSize)
                .setInitialLoadSizeHint(pageSize)
                .build()
        )
            .setFetchScheduler(Schedulers.io())
            .buildObservable()
    }
}

I should be one of the first people to try paging. When I first tasted it, I thought it was not good. This project suddenly reminded me of this library, so I took it out to practice, especially after watching it Paging, the official architecture component of Android: design aesthetics of paging Library After this article, there are more hopes for this library. However, after this large-scale use, I really have a hole in myself. The current thoughts are as follows:

  1. First of all, it's really too cumbersome to use. In fact, Google has the ability to simplify it. For example, based on my above writing method, plus enumeration to generate different data sources (a bit shameful). But after several versions, this problem has not improved. Secondly, we need to introduce the pageAdapter, which inherits from the ListAdapter, so the data can only be of type list < > and the enumeration I like to use is excluded. If I want to add a header or a footer to a list, I need to create a data model specifically for h/f and insert the data mode into the list before submitList(), which leads to a series of problems such as removing the footer before adding to the next page. It's not worth the loss.

  2. This library is completely developed in accordance with the jetpack Architecture Guide. It can't directly and dynamically modify item s and refresh them!! (pagedList actually inherits from abstractList and cannot call add, remove and set methods.) although there are several ways to complete this kind of "universal" operation, it will seriously damage the code structure and lose more than it deserves. The best way is to follow the guidelines of jetpack architecture, introduce database as hard disk cache, modify data dynamically and store it into database, and automatically refresh UI by observing database. But in this way, a simple temporary list of dynamic data acquisition through the network is added to the database operation. Every time we start, we need to clear the database cache first, then put in new data, and then refresh the UI, which increases the efficiency of hard disk reading and writing, not to mention that once the product head blows, or the back-end guy changes the table field, it means that we need to corresponding Do database upgrade, even if the important data, the key is only a temporary list ah!

  3. Wugan refresh is great, we all think it's great, but... Second, product managers like to show the loading more for three seconds, which is named as "more interaction is more beautiful for users!"! What to do at this time?

So I think paging is really a good thing. The code is thoughtful. But after all, it is not flexible enough, and its limitations are too big. It can not stand the test of many scenes. It knows what the product is thinking every day.

Posted by sy-co on Wed, 03 Jun 2020 06:58:43 -0700