Paging An introduction to the Paging library

Paging page page is a new architecture library launched by Google combined with RecyclerView for Paging loading data. It is mainly to solve the problem of resource waste caused by loading a large amount of data at one time. By paging, one page of data is loaded at a time, which not only speeds up the rendering of the interface, but also reduces the consumption of creating resources such as objects. Specific can see the official website

The paging library consists of three main parts

  • DataSource: Defines a method for obtaining data. There are three methods

    1. PageKeyedDataSource 2. ItemKeyedDataSource 3. PositionalDataSource. Load data based on location information, in conjunction with Room database or local data source.Copy the code
  • PagedListAdapter: a page library adapter that inherits from RecyclerView and implements a DiffUtil.ItemCallback differentiator to analyze whether data has changed.

  • PagedList: Defines the configuration of the pagination library, which has the default load data size, pagination data size, etc. And through the PagedListAdapter data changes are updated.

First, perform paging loading through local data

(1) The creation of a DataSource

In this case, we need to implement a PositionalDataSource based data source

class LocalDataSourceFactory:DataSource.Factory<Int, ArticleEntity>() {
    override fun create(): DataSource<Int, ArticleEntity> {
        return localDataSource
    }

    companion object {
        val localDataSource = object : PositionalDataSource<ArticleEntity>() {
            private fun computeCount(): Int {
                return 10000
            }
            private fun loadRangeInternal(startPosition: Int, loadCount: Int): List<ArticleEntity> {
                val articleList = mutableListOf<ArticleEntity>()
                val authorPrefix = "The author"
                val titlePrefix = "I am a title."
                val typePrefix = "Category"
                val timeStampBase = 1531548138000L
                for (i in 0 until loadCount) {
                    var articleEntity = ArticleEntity()
                    articleEntity.id = (startPosition + i).toString()
                    articleEntity.author = "$authorPrefix ${articleEntity.id}"
                    articleEntity.title = "$titlePrefix ${articleEntity.id}"
                    articleEntity.type = "$typePrefix ${articleEntity.id}"
                    articleEntity.timeStamp = timeStampBase + i * 1000L
                    articleList.add(articleEntity)
                }
                return articleList
            }

            override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<ArticleEntity>) {
                Log.e("LoadRange"."range" + params.startPosition)
                callback.onResult(loadRangeInternal(params.startPosition, params.loadSize))
            }

            override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<ArticleEntity>) {
                val totalCount = computeCount()
                val position = PositionalDataSource.computeInitialLoadPosition(params, totalCount)
                val loadSize = PositionalDataSource.computeInitialLoadSize(params, position, totalCount)
                callback.onResult(loadRangeInternal(position, loadSize), position, totalCount)
            }
        }
    }

}
Copy the code

The PositionalDataSource needs to be implemented in two methods: loadInitial and loadRange. LoadInitial is responsible for pulling the number of loads configured, that is, the PagedList configuration below, and loadRange is responsible for loading the data required by each page. So implementing the data source is as simple as defining the logic for first loading the data and paging the data.

(2) The implementation of PagedListAdapter

Because PagedListAdapter inherited from RecyclerView adapter, so it is not difficult to achieve, just need to provide a difference implementation used for data analysis, the code is as follows:

class ArticlePageAdapter : PagedListAdapter<ArticleEntity, ArticleViewHolder>(diffCallback) {
    override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
        holder.bindTo(getItem(position))
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder =
            ArticleViewHolder(parent)

    companion object {
        private val diffCallback = object : DiffUtil.ItemCallback<ArticleEntity>() {
            override fun areItemsTheSame(oldItem: ArticleEntity, newItem: ArticleEntity): Boolean =
                    oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: ArticleEntity, newItem: ArticleEntity): Boolean =
                    oldItem == newItem
        }
    }
}
Copy the code

(3) Configure PagedList

PagedList sets the size of pages, initializes the size of data to be loaded, and so on.

 val pagedListConfig =PagedList.Config.Builder().setEnablePlaceholders(true).setPageSize(10).setInitialLoadSizeHint(20).build()
 var postList = LivePagedListBuilder(LocalDataSourceFactory(), pagedListConfig).build()
Copy the code

Generated from the above code is a PagedList with LiveData

(4) Summary

The DataSource is responsible for the DataSource, then the PagedListAdapter is responsible for rendering the UI, and finally the PagedList is configured. Generate a PagedList with LiveData, and notify the pageAdapter to call submitList to update the UI once the data changes

class LocalDataPagingActivity:AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.act_local_data_paging) val pageAdapter = ArticlePageAdapter() recycle_article.adapter = pageAdapter  recycle_article.layoutManager = LinearLayoutManager(this) val pagedListConfig = PagedList.Config.Builder().setEnablePlaceholders(true).setPageSize(10).setInitialLoadSizeHint(20).build()
        var postList = LivePagedListBuilder(LocalDataSourceFactory(), pagedListConfig).build()
        postList.observe(this, Observer {
            pageAdapter.submitList(it)
        })
    }
}
Copy the code

The demo has been uploaded, click on the portal, if there is any doubt or error, welcome to point out. Android Paging library (2) — Paging loading in conjunction with the Room database