paging数据源的二次封装及我目前的认识

瘦欲@ 提交于 2020-07-27 23:15:55

说实话,pagging的数据源定义是在是太繁琐了,所以二次封装了下,没有任何侵入,干净利落,暂时先留存下来,或许在我的生命之中还能用到。。

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()
    }
}

我应该算是第一批尝试paging这个库的人之一吧,第一次尝鲜的时候就觉得这个库不行,这次的项目我突然想起这个库,就又拿出来练手玩,尤其是看过Android官方架构组件Paging:分页库的设计美学这篇文章之后,对这个库增加了更多的憧憬。 然而经过这次的大量使用后,着实坑了自己一把。现有感想如下:

  1. 首先使用起来真的太繁琐了,其实谷歌完全有能力简化它,比如基于我上面的写法,再加上枚举来生成不同的数据源(有点大言不惭了)但是几个版本下来,这个问题并没有改善。其次是还要再引入pageAdapter,而pageAdapter继承自ListAdapter,那么就限制了数据只能是List<>类型,也就把我喜欢使用的枚举排除在外了。如果想给列表加个header或者footer,我需要专门为h/f创建一个数据模型,还要在submitList()之前把数据模式插入到list中,这样又造成了加在下一页时要先去除footer等一系列问题,实在得不偿失。

  2. 这个库完全就是配合jetpack架构指南开发的,不能直观地动态修改item并刷新!!(pagedList竟然继承自abstractList,不能调用add、remove、set方法)虽然有多达几种方式去完成这种「普遍」操作,然而会严重破坏代码结构,得不偿失。最好的办法就是遵循jetpack架构指南,引入数据库做硬盘缓存,动态修改数据后硬缓存入数据库,并通过观察数据库自动完成UI刷新。但是这样一来,本来简单的一个纯网络动态获取数据的临时列表,就加入了数据库操作,每次启动我们都需要先清掉数据库缓存,再放入新数据,再刷新UI,增加了硬盘读写降低效率不说,一旦产品脑袋抽风,或者后端小伙子改了表字段,那就意味着我们需要对应的做数据库升级,重要数据也就算了,关键这只是临时列表啊!

  3. 无感刷新很棒,我们搞开发的都觉得很棒,但是。。。二逼产品经理就喜欢展示3秒钟的loadingMore,美名其曰:多一个交互就对用户多一份美好!此时咋办?

所以我觉得,paging确实是一个不错的玩意,代码很有思想。但是它毕竟不够灵活,局限实在太大,经不起多场景下的考验,鬼知道产品每天在想啥。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!