liangjingkanji / BRV

[使用文档] Android 快速构建 RecyclerView, 比 BRVAH 更简单强大
http://liangjingkanji.github.io/BRV/
MIT License
2.59k stars 327 forks source link

BindingAdapter分页加载需求下组的合并的方法 #425

Open XXQAQ opened 7 months ago

XXQAQ commented 7 months ago

描述

现有的BindingAdapter的addModels内部处理好了分组的嵌套结构,但目前的方式是将新增的所有元素视为一个完整的嵌套组进行处理。 在绝大多数异步分页加载中,组的数量不恒定,会随着分页加载数据的增多而增多。所以每次请求到的数据可能属于在上一页数据中的最后一个分组(也就是一个组的数据会跨多页)。 并且考虑到组与组是可以递归嵌套的,需要写非常复杂的算法才能将多组的数据进行合并。所以我提供了一种算法,可以递归合并分组数据 joinMergeModels 方法的含义是: 每次调用该方法时,如果当前List中的第一个组与Models中的最后一个组为同一组,那么将当前List的第一组合并至Models的最后一组中。该算法支持组的递归嵌套关系,用中文来描述意思就是:支持当前List的第一个组的第一个组的一个组的...的数据与Models中的最后一个组的最后一个组的最后一个组...的数据进行合并

参考实现

fun joinMergeModels(list: List<Any?>?){
    if (list.isNullOrEmpty()){
        return
    }
    val insertIndex = modelCount
    val byAffectedList = ArrayList<Any?>()
    val flatList = mergeList(expandListToCollapseList(mutable),list.toMutableList(),byAffectedList)
    //先新增
    mutable.addAll(flatList)
    notifyItemRangeInserted(insertIndex, flatList.size)
    //将受到影响的父节点挨个更新
    for (affected in byAffectedList.reversed()){
        notifyItemChanged(mutable.indexOf(affected))
    }
    //
    rv?.post {
        rv?.invalidateItemDecorations()
    }
}

private fun mergeList(srcList: MutableList<Any?>, insertList: MutableList<Any?>, byAffectedList: MutableList<Any?>): List<Any?>{
    val flatList = ArrayList<Any?>()
    val firstInInsert = insertList.firstOrNull()
    val lastInSrc = srcList.lastOrNull()
    if (lastInSrc is ItemExpand && firstInInsert is ItemExpand && lastInSrc is ItemStableId && firstInInsert is ItemStableId && lastInSrc.getItemId() == firstInInsert.getItemId()){
        byAffectedList.add(lastInSrc)
        val lastFlatGroupList = mergeList(lastInSrc.getItemSublist(),firstInInsert.getItemSublist(),byAffectedList)
        if (lastInSrc.itemExpand){
            flatList.addAll(lastFlatGroupList)
        }
        flatList.addAll(insertAndFlat(srcList,insertList.subList(1,insertList.size)))
    } else{
        flatList.addAll(insertAndFlat(srcList,insertList))
    }
    return flatList
}

private fun insertAndFlat(srcList: MutableList<Any?>, insertList: MutableList<Any?>): List<Any?>{
    srcList.addAll(insertList)
    return flat(insertList)
}

private fun expandListToCollapseList(list: List<Any?>): MutableList<Any?>{
    val result = ArrayList<Any?>()
    for (any in list){
        val last = result.lastOrNull()
        if (last is ItemExpand && isNestedChild(last,any)){
            // 不用再递归了
        } else{
            result.add(any)
        }
    }
    return result
}

private fun isNestedChild(itemExpand: ItemExpand,any: Any?): Boolean{
    return itemExpand.getItemSublist().contains(any) || itemExpand.getItemSublist().any {
        it is ItemExpand && isNestedChild(it,any)
    }
}