本文給出了我對(duì)與當(dāng)前Paging+Network數(shù)據(jù)修改的處理方法
網(wǎng)絡(luò)上的處理方案
1、簡單粗暴,直接刷新數(shù)據(jù)使用
adapter?.currentlist?.dataSource?.invalidate()
這樣會(huì)重新調(diào)用init初始化數(shù)據(jù),刷新頁面。
缺點(diǎn):刷新后會(huì)回到列表頂部,不能刷新到分頁處。需要重新load數(shù)據(jù)
明顯該方案在分頁數(shù)據(jù)的情況下,體驗(yàn)很糟糕基本上是不可取的
2、借助db或者memory緩存來實(shí)現(xiàn),具體可以參考官方的demo,本質(zhì)上是多了一級(jí)存儲(chǔ),不過db或memory上數(shù)據(jù)的變化會(huì)實(shí)時(shí)刷新到頁面
缺點(diǎn):實(shí)現(xiàn)相對(duì)比較復(fù)雜,而且多了一級(jí)緩存,需要考慮緩存的更新同步策略。
總結(jié):在方案一不可取,方案二又顯得冗余的情況下,難道真的要妥協(xié)了嗎?有沒有既能實(shí)現(xiàn)效果,又不那么復(fù)雜的方法呢?
我的方案
既然要對(duì)數(shù)據(jù)做增刪改,在和服務(wù)端交互完成后,我們自己是知道修改后數(shù)據(jù)是什么樣的,自然能通過現(xiàn)有數(shù)據(jù)構(gòu)造出新的數(shù)據(jù)來。這里我們不事先緩存所有數(shù)據(jù),只是增刪改之后自己生成增刪改之后的數(shù)據(jù)。然后就是怎么刷新到頁面上了,這個(gè)問題很簡單,我們借助adapter?.currentlist?.dataSource?.invalidate(),調(diào)用之后會(huì)重新調(diào)用DataSource的loadInitial方法去重新初始化數(shù)據(jù),這里我們就不再去網(wǎng)絡(luò)請(qǐng)求了,直接使用我們構(gòu)造的數(shù)據(jù),這樣整個(gè)流程就連接起來了,這里需要注意的有兩點(diǎn),一個(gè)是我們自己構(gòu)造的數(shù)據(jù)只能在我們?cè)鰟h改之后使用,使用完了就沒有用了可以清除了。另一個(gè)就是我們自己構(gòu)造的數(shù)據(jù)如何給DataSource,這里我們考慮到由于沒有通過網(wǎng)絡(luò)請(qǐng)求,所有數(shù)據(jù)構(gòu)造以及到loadInitial過程都是同步,且DataSource在invalidate后會(huì)重新創(chuàng)建,所以構(gòu)造的數(shù)據(jù)用一個(gè)靜態(tài)變量存儲(chǔ),雖然數(shù)據(jù)可能會(huì)很大,但是這個(gè)數(shù)據(jù)存在時(shí)間很短暫,用完就清除了,所以代價(jià)算是比較小吧。
下面是簡單的代碼:
首先添加用于存儲(chǔ)臨時(shí)數(shù)據(jù)的變量,然后添加一個(gè)外部調(diào)用的post更新后的數(shù)據(jù)的方法。
val DataSource<*, *>.tempList: MutableList<Any>
get() = tempDataSourceList
//存儲(chǔ)構(gòu)建的用于本地刷新的臨時(shí)數(shù)據(jù)
val tempDataSourceList:MutableList<Any> = ArrayList()
//給出構(gòu)造的數(shù)據(jù),并發(fā)出刷新動(dòng)作
fun DataSource<*, *>.postChangedList(list: List<Any>){
tempList.clear()
tempList.addAll(list)
invalidate()
}
fun DataSource<*, *>.isLocalUpdate():Boolean{
return tempList.isNotEmpty()
}
然后再對(duì)應(yīng)DataSource的loadInitial方法中做如下判斷:
//如果是本地刷新,直接傳入數(shù)據(jù)返回
if (isLocalUpdate()) {
initSuccess(tempList)
//臨時(shí)數(shù)據(jù)使用完成及時(shí)清除
tempList.clear()
return
}
//正常邏輯,請(qǐng)求然后刷新數(shù)據(jù)
//...
接下來是增刪改之后調(diào)用:
val currentList = adapter.currentList?.snapshot()
// ...對(duì)數(shù)據(jù)做具體增刪改操作,以刪除最后一條數(shù)據(jù)為例
currentList?.removeAt(currentList.lastIndex)
adapter.currentList?.dataSource?.postChangedList(currentList?.toList()?: emptyList())
沒錯(cuò)就是這么簡單,全部加起來也不過十幾行代碼,第一部分是通用的代碼,其余的是在自己業(yè)務(wù)代碼的地方添加。
如果有不正確的地方或者還有可優(yōu)化的地方歡迎指出。