本文给出了我对与当前Paging+Network数据修改的处理方法
网络上的处理方案
1、简单粗暴,直接刷新数据使用
adapter?.currentlist?.dataSource?.invalidate()
这样会重新调用init初始化数据,刷新页面。
缺点:刷新后会回到列表顶部,不能刷新到分页处。需要重新load数据
明显该方案在分页数据的情况下,体验很糟糕基本上是不可取的
2、借助db或者memory缓存来实现,具体可以参考官方的demo,本质上是多了一级存储,不过db或memory上数据的变化会实时刷新到页面
缺点:实现相对比较复杂,而且多了一级缓存,需要考虑缓存的更新同步策略。
总结:在方案一不可取,方案二又显得冗余的情况下,难道真的要妥协了吗?有没有既能实现效果,又不那么复杂的方法呢?
我的方案
既然要对数据做增删改,在和服务端交互完成后,我们自己是知道修改后数据是什么样的,自然能通过现有数据构造出新的数据来。这里我们不事先缓存所有数据,只是增删改之后自己生成增删改之后的数据。然后就是怎么刷新到页面上了,这个问题很简单,我们借助adapter?.currentlist?.dataSource?.invalidate(),调用之后会重新调用DataSource的loadInitial方法去重新初始化数据,这里我们就不再去网络请求了,直接使用我们构造的数据,这样整个流程就连接起来了,这里需要注意的有两点,一个是我们自己构造的数据只能在我们增删改之后使用,使用完了就没有用了可以清除了。另一个就是我们自己构造的数据如何给DataSource,这里我们考虑到由于没有通过网络请求,所有数据构造以及到loadInitial过程都是同步,且DataSource在invalidate后会重新创建,所以构造的数据用一个静态变量存储,虽然数据可能会很大,但是这个数据存在时间很短暂,用完就清除了,所以代价算是比较小吧。
下面是简单的代码:
首先添加用于存储临时数据的变量,然后添加一个外部调用的post更新后的数据的方法。
val DataSource<*, *>.tempList: MutableList<Any>
get() = tempDataSourceList
//存储构建的用于本地刷新的临时数据
val tempDataSourceList:MutableList<Any> = ArrayList()
//给出构造的数据,并发出刷新动作
fun DataSource<*, *>.postChangedList(list: List<Any>){
tempList.clear()
tempList.addAll(list)
invalidate()
}
fun DataSource<*, *>.isLocalUpdate():Boolean{
return tempList.isNotEmpty()
}
然后再对应DataSource的loadInitial方法中做如下判断:
//如果是本地刷新,直接传入数据返回
if (isLocalUpdate()) {
initSuccess(tempList)
//临时数据使用完成及时清除
tempList.clear()
return
}
//正常逻辑,请求然后刷新数据
//...
接下来是增删改之后调用:
val currentList = adapter.currentList?.snapshot()
// ...对数据做具体增删改操作,以删除最后一条数据为例
currentList?.removeAt(currentList.lastIndex)
adapter.currentList?.dataSource?.postChangedList(currentList?.toList()?: emptyList())
没错就是这么简单,全部加起来也不过十几行代码,第一部分是通用的代码,其余的是在自己业务代码的地方添加。
如果有不正确的地方或者还有可优化的地方欢迎指出。